@fireproof/core 0.20.5 → 0.21.0-dev-preview-3
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/blockstore/commitor.js +3 -3
- package/blockstore/commitor.js.map +1 -1
- package/blockstore/loader.d.ts +2 -1
- package/blockstore/loader.d.ts.map +1 -1
- package/blockstore/loader.js +40 -10
- package/blockstore/loader.js.map +1 -1
- package/blockstore/store.js +1 -1
- package/blockstore/store.js.map +1 -1
- package/crdt.d.ts +1 -1
- package/crdt.d.ts.map +1 -1
- package/crdt.js.map +1 -1
- package/database.d.ts +2 -3
- package/database.d.ts.map +1 -1
- package/database.js +7 -3
- package/database.js.map +1 -1
- package/deno.json +1 -1
- package/index.d.ts +1 -0
- package/index.d.ts.map +1 -1
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/indexer-helpers.d.ts +29 -28
- package/indexer-helpers.d.ts.map +1 -1
- package/indexer-helpers.js +21 -3
- package/indexer-helpers.js.map +1 -1
- package/indexer.d.ts +3 -3
- package/indexer.d.ts.map +1 -1
- package/indexer.js +16 -24
- package/indexer.js.map +1 -1
- package/ledger.d.ts +3 -2
- package/ledger.d.ts.map +1 -1
- package/ledger.js +7 -4
- package/ledger.js.map +1 -1
- package/package.json +2 -2
- package/protocols/cloud/http-connection.d.ts +2 -1
- package/protocols/cloud/http-connection.d.ts.map +1 -1
- package/protocols/cloud/http-connection.js +1 -0
- package/protocols/cloud/http-connection.js.map +1 -1
- package/protocols/cloud/msg-types-data.d.ts +4 -4
- package/protocols/cloud/msg-types-data.d.ts.map +1 -1
- package/protocols/cloud/msg-types-data.js.map +1 -1
- package/protocols/cloud/msg-types-meta.d.ts +13 -13
- package/protocols/cloud/msg-types-meta.d.ts.map +1 -1
- package/protocols/cloud/msg-types-meta.js.map +1 -1
- package/protocols/cloud/msg-types-wal.d.ts +4 -4
- package/protocols/cloud/msg-types-wal.d.ts.map +1 -1
- package/protocols/cloud/msg-types-wal.js.map +1 -1
- package/protocols/cloud/msg-types.d.ts +33 -19
- package/protocols/cloud/msg-types.d.ts.map +1 -1
- package/protocols/cloud/msg-types.js +4 -1
- package/protocols/cloud/msg-types.js.map +1 -1
- package/protocols/cloud/msger.d.ts +47 -38
- package/protocols/cloud/msger.d.ts.map +1 -1
- package/protocols/cloud/msger.js +211 -106
- package/protocols/cloud/msger.js.map +1 -1
- package/protocols/cloud/ws-connection.d.ts +14 -3
- package/protocols/cloud/ws-connection.d.ts.map +1 -1
- package/protocols/cloud/ws-connection.js +73 -34
- package/protocols/cloud/ws-connection.js.map +1 -1
- package/protocols/dashboard/index.d.ts +4 -0
- package/protocols/dashboard/index.d.ts.map +1 -0
- package/protocols/dashboard/index.js +4 -0
- package/protocols/dashboard/index.js.map +1 -0
- package/protocols/dashboard/msg-api.d.ts +11 -0
- package/protocols/dashboard/msg-api.d.ts.map +1 -0
- package/protocols/dashboard/msg-api.js +55 -0
- package/protocols/dashboard/msg-api.js.map +1 -0
- package/protocols/dashboard/msg-is.d.ts +45 -0
- package/protocols/dashboard/msg-is.d.ts.map +1 -0
- package/protocols/dashboard/msg-is.js +63 -0
- package/protocols/dashboard/msg-is.js.map +1 -0
- package/protocols/dashboard/msg-types.d.ts +397 -0
- package/protocols/dashboard/msg-types.d.ts.map +1 -0
- package/protocols/dashboard/msg-types.js +4 -0
- package/protocols/dashboard/msg-types.js.map +1 -0
- package/protocols/index.d.ts +1 -0
- package/protocols/index.d.ts.map +1 -1
- package/protocols/index.js +1 -0
- package/protocols/index.js.map +1 -1
- package/react/img-file.d.ts +2 -2
- package/react/img-file.d.ts.map +1 -1
- package/react/img-file.js +62 -27
- package/react/img-file.js.map +1 -1
- package/react/types.d.ts +29 -9
- package/react/types.d.ts.map +1 -1
- package/react/use-all-docs.d.ts +1 -1
- package/react/use-all-docs.d.ts.map +1 -1
- package/react/use-all-docs.js.map +1 -1
- package/react/use-attach.d.ts +9 -4
- package/react/use-attach.d.ts.map +1 -1
- package/react/use-attach.js +136 -43
- package/react/use-attach.js.map +1 -1
- package/react/use-fireproof.js +2 -2
- package/react/use-fireproof.js.map +1 -1
- package/react/use-live-query.d.ts.map +1 -1
- package/react/use-live-query.js +1 -4
- package/react/use-live-query.js.map +1 -1
- package/runtime/gateways/cloud/gateway.d.ts +8 -8
- package/runtime/gateways/cloud/gateway.d.ts.map +1 -1
- package/runtime/gateways/cloud/gateway.js +17 -15
- package/runtime/gateways/cloud/gateway.js.map +1 -1
- package/runtime/gateways/cloud/to-cloud.d.ts +22 -9
- package/runtime/gateways/cloud/to-cloud.d.ts.map +1 -1
- package/runtime/gateways/cloud/to-cloud.js +75 -59
- package/runtime/gateways/cloud/to-cloud.js.map +1 -1
- package/runtime/gateways/file/key-bag-file.d.ts +1 -0
- package/runtime/gateways/file/key-bag-file.d.ts.map +1 -1
- package/runtime/gateways/file/key-bag-file.js +12 -0
- package/runtime/gateways/file/key-bag-file.js.map +1 -1
- package/runtime/gateways/indexeddb/gateway-impl.d.ts.map +1 -1
- package/runtime/gateways/indexeddb/gateway-impl.js.map +1 -1
- package/runtime/gateways/indexeddb/key-bag-indexeddb.d.ts +1 -0
- package/runtime/gateways/indexeddb/key-bag-indexeddb.d.ts.map +1 -1
- package/runtime/gateways/indexeddb/key-bag-indexeddb.js +6 -0
- package/runtime/gateways/indexeddb/key-bag-indexeddb.js.map +1 -1
- package/runtime/key-bag-memory.d.ts +1 -0
- package/runtime/key-bag-memory.d.ts.map +1 -1
- package/runtime/key-bag-memory.js +7 -0
- package/runtime/key-bag-memory.js.map +1 -1
- package/runtime/key-bag.d.ts +3 -0
- package/runtime/key-bag.d.ts.map +1 -1
- package/runtime/key-bag.js +6 -0
- package/runtime/key-bag.js.map +1 -1
- package/tests/fireproof/attachable.test.ts +1 -1
- package/tests/fireproof/charwise-boolean.test.ts +66 -0
- package/tests/fireproof/crdt.test.ts +3 -3
- package/tests/fireproof/deleted-docs-handling.test.ts +111 -0
- package/tests/fireproof/fireproof.test.ts +10 -10
- package/tests/fireproof/hello.test.ts +1 -1
- package/tests/fireproof/indexer.test.ts +21 -21
- package/tests/fireproof/query-docs.test.ts +42 -7
- package/tests/fireproof/query-limit-issue.test.ts +147 -0
- package/tests/fireproof/query-property-inconsistency.test.ts +89 -0
- package/tests/fireproof/query-result-properties.test.ts +42 -0
- package/tests/protocols/cloud/msger.test.ts +563 -0
- package/types.d.ts +9 -9
- package/types.d.ts.map +1 -1
- package/types.js.map +1 -1
- package/use-fireproof/iframe-strategy.d.ts +6 -4
- package/use-fireproof/iframe-strategy.d.ts.map +1 -1
- package/use-fireproof/iframe-strategy.js +7 -11
- package/use-fireproof/iframe-strategy.js.map +1 -1
- package/use-fireproof/index.d.ts +6 -2
- package/use-fireproof/index.d.ts.map +1 -1
- package/use-fireproof/index.js +23 -3
- package/use-fireproof/index.js.map +1 -1
- package/use-fireproof/redirect-strategy.d.ts +11 -4
- package/use-fireproof/redirect-strategy.d.ts.map +1 -1
- package/use-fireproof/redirect-strategy.js +142 -20
- package/use-fireproof/redirect-strategy.js.map +1 -1
- package/utils.d.ts +3 -0
- package/utils.d.ts.map +1 -1
- package/utils.js.map +1 -1
@@ -23,7 +23,7 @@ interface TestType {
|
|
23
23
|
|
24
24
|
describe("basic Index", () => {
|
25
25
|
let db: Database;
|
26
|
-
let indexer: Index<
|
26
|
+
let indexer: Index<TestType, string>;
|
27
27
|
let didMap: boolean;
|
28
28
|
const sthis = ensureSuperThis();
|
29
29
|
afterEach(async () => {
|
@@ -38,7 +38,7 @@ describe("basic Index", () => {
|
|
38
38
|
await db.put({ title: "amazing" });
|
39
39
|
await db.put({ title: "creative" });
|
40
40
|
await db.put({ title: "bazillas" });
|
41
|
-
indexer = new Index<
|
41
|
+
indexer = new Index<TestType, string>(sthis, db.ledger.crdt, "hello", (doc) => {
|
42
42
|
didMap = true;
|
43
43
|
return doc.title;
|
44
44
|
});
|
@@ -111,7 +111,7 @@ describe("basic Index", () => {
|
|
111
111
|
|
112
112
|
describe("Index query with compound key", function () {
|
113
113
|
let db: Database;
|
114
|
-
let indexer: Index<[string, number]
|
114
|
+
let indexer: Index<TestType, [string, number]>;
|
115
115
|
const sthis = ensureSuperThis();
|
116
116
|
afterEach(async () => {
|
117
117
|
await db.close();
|
@@ -126,7 +126,7 @@ describe("Index query with compound key", function () {
|
|
126
126
|
await db.put({ title: "creative", score: 2 });
|
127
127
|
await db.put({ title: "creative", score: 20 });
|
128
128
|
await db.put({ title: "bazillas", score: 3 });
|
129
|
-
indexer = new Index<[string, number]
|
129
|
+
indexer = new Index<TestType, [string, number]>(sthis, db.ledger.crdt, "hello", (doc) => {
|
130
130
|
return [doc.title, doc.score];
|
131
131
|
});
|
132
132
|
await indexer.ready();
|
@@ -141,7 +141,7 @@ describe("Index query with compound key", function () {
|
|
141
141
|
|
142
142
|
describe("basic Index with map fun", function () {
|
143
143
|
let db: Database;
|
144
|
-
let indexer: Index<
|
144
|
+
let indexer: Index<TestType, string>;
|
145
145
|
const sthis = ensureSuperThis();
|
146
146
|
afterEach(async () => {
|
147
147
|
await db.close();
|
@@ -155,7 +155,7 @@ describe("basic Index with map fun", function () {
|
|
155
155
|
await db.put({ title: "amazing" });
|
156
156
|
await db.put({ title: "creative" });
|
157
157
|
await db.put({ title: "bazillas" });
|
158
|
-
indexer = new Index<
|
158
|
+
indexer = new Index<TestType, string>(sthis, db.ledger.crdt, "hello", (doc, map) => {
|
159
159
|
map(doc.title);
|
160
160
|
});
|
161
161
|
await indexer.ready();
|
@@ -171,7 +171,7 @@ describe("basic Index with map fun", function () {
|
|
171
171
|
|
172
172
|
describe("basic Index with map fun with value", function () {
|
173
173
|
let db: Database;
|
174
|
-
let indexer: Index<
|
174
|
+
let indexer: Index<TestType, string, number>;
|
175
175
|
const sthis = ensureSuperThis();
|
176
176
|
afterEach(async () => {
|
177
177
|
await db.close();
|
@@ -183,7 +183,7 @@ describe("basic Index with map fun with value", function () {
|
|
183
183
|
await db.put({ title: "amazing" });
|
184
184
|
await db.put({ title: "creative" });
|
185
185
|
await db.put({ title: "bazillas" });
|
186
|
-
indexer = new Index<
|
186
|
+
indexer = new Index<TestType, string, number>(sthis, db.ledger.crdt, "hello", (doc, map) => {
|
187
187
|
map(doc.title, doc.title.length);
|
188
188
|
});
|
189
189
|
});
|
@@ -209,7 +209,7 @@ describe("basic Index with map fun with value", function () {
|
|
209
209
|
|
210
210
|
describe("Index query with map and compound key", function () {
|
211
211
|
let db: Database;
|
212
|
-
let indexer: Index<[string, number]
|
212
|
+
let indexer: Index<TestType, [string, number]>;
|
213
213
|
const sthis = ensureSuperThis();
|
214
214
|
afterEach(async () => {
|
215
215
|
await db.close();
|
@@ -224,7 +224,7 @@ describe("Index query with map and compound key", function () {
|
|
224
224
|
await db.put({ title: "creative", score: 2 });
|
225
225
|
await db.put({ title: "creative", score: 20 });
|
226
226
|
await db.put({ title: "bazillas", score: 3 });
|
227
|
-
indexer = new Index<[string, number]
|
227
|
+
indexer = new Index<TestType, [string, number]>(sthis, db.ledger.crdt, "hello", (doc, emit) => {
|
228
228
|
emit([doc.title, doc.score]);
|
229
229
|
});
|
230
230
|
await indexer.ready();
|
@@ -239,7 +239,7 @@ describe("Index query with map and compound key", function () {
|
|
239
239
|
|
240
240
|
describe("basic Index with string fun", function () {
|
241
241
|
let db: Database;
|
242
|
-
let indexer: Index<
|
242
|
+
let indexer: Index<TestType, string>;
|
243
243
|
const sthis = ensureSuperThis();
|
244
244
|
afterEach(async () => {
|
245
245
|
await db.close();
|
@@ -253,7 +253,7 @@ describe("basic Index with string fun", function () {
|
|
253
253
|
await db.put({ title: "amazing" });
|
254
254
|
await db.put({ title: "creative" });
|
255
255
|
await db.put({ title: "bazillas" });
|
256
|
-
indexer = new Index<
|
256
|
+
indexer = new Index<TestType, string>(sthis, db.ledger.crdt, "title");
|
257
257
|
await indexer.ready();
|
258
258
|
});
|
259
259
|
it("should get results", async () => {
|
@@ -271,7 +271,7 @@ describe("basic Index with string fun", function () {
|
|
271
271
|
|
272
272
|
describe("basic Index with string fun and numeric keys", function () {
|
273
273
|
let db: Database;
|
274
|
-
let indexer: Index<
|
274
|
+
let indexer: Index<TestType, string>;
|
275
275
|
const sthis = ensureSuperThis();
|
276
276
|
afterEach(async () => {
|
277
277
|
await db.close();
|
@@ -286,7 +286,7 @@ describe("basic Index with string fun and numeric keys", function () {
|
|
286
286
|
await db.put({ points: 1 });
|
287
287
|
await db.put({ points: 2 });
|
288
288
|
await db.put({ points: 3 });
|
289
|
-
indexer = new Index<
|
289
|
+
indexer = new Index<TestType, string>(sthis, db.ledger.crdt, "points");
|
290
290
|
await indexer.ready();
|
291
291
|
});
|
292
292
|
it("should get results", async () => {
|
@@ -308,10 +308,10 @@ describe("basic Index upon cold start", function () {
|
|
308
308
|
score?: number;
|
309
309
|
}
|
310
310
|
let crdt: CRDT;
|
311
|
-
let indexer: Index<
|
311
|
+
let indexer: Index<TestType>;
|
312
312
|
let didMap: number;
|
313
313
|
let mapFn: (doc: TestType) => string;
|
314
|
-
let result: IndexRows<
|
314
|
+
let result: IndexRows<TestType>;
|
315
315
|
const sthis = ensureSuperThis();
|
316
316
|
let dbOpts: LedgerOpts;
|
317
317
|
// result, mapFn;
|
@@ -346,7 +346,7 @@ describe("basic Index upon cold start", function () {
|
|
346
346
|
didMap++;
|
347
347
|
return doc.title;
|
348
348
|
};
|
349
|
-
indexer = await index<
|
349
|
+
indexer = await index<TestType>(crdt, "hello", mapFn);
|
350
350
|
logger.Debug().Msg("post index beforeEach");
|
351
351
|
await indexer.ready();
|
352
352
|
logger.Debug().Msg("post indexer.ready beforeEach");
|
@@ -371,7 +371,7 @@ describe("basic Index upon cold start", function () {
|
|
371
371
|
const { result, head } = await crdt2.changes();
|
372
372
|
expect(result).toBeTruthy();
|
373
373
|
await crdt2.ready();
|
374
|
-
const indexer2 = await index<
|
374
|
+
const indexer2 = await index<TestType>(crdt2, "hello", mapFn);
|
375
375
|
await indexer2.ready();
|
376
376
|
const result2 = await indexer2.query();
|
377
377
|
expect(indexer2.indexHead).toEqual(head);
|
@@ -407,7 +407,7 @@ describe("basic Index upon cold start", function () {
|
|
407
407
|
});
|
408
408
|
it("should ignore meta when map function definiton changes", async () => {
|
409
409
|
const crdt2 = new CRDTImpl(sthis, dbOpts);
|
410
|
-
const result = await index<
|
410
|
+
const result = await index<TestType>(crdt2, "hello", (doc) => doc.title.split("").reverse().join("")).query();
|
411
411
|
expect(result.rows.length).toEqual(3);
|
412
412
|
expect(result.rows[0].key).toEqual("evitaerc"); // creative
|
413
413
|
});
|
@@ -415,7 +415,7 @@ describe("basic Index upon cold start", function () {
|
|
415
415
|
|
416
416
|
describe("basic Index with no data", function () {
|
417
417
|
let db: Database;
|
418
|
-
let indexer: Index<
|
418
|
+
let indexer: Index<TestType>;
|
419
419
|
let didMap: boolean;
|
420
420
|
const sthis = ensureSuperThis();
|
421
421
|
afterEach(async () => {
|
@@ -427,7 +427,7 @@ describe("basic Index with no data", function () {
|
|
427
427
|
beforeEach(async () => {
|
428
428
|
await sthis.start();
|
429
429
|
db = fireproof("test-indexer");
|
430
|
-
indexer = new Index<
|
430
|
+
indexer = new Index<TestType>(sthis, db.ledger.crdt, "hello", (doc) => {
|
431
431
|
didMap = true;
|
432
432
|
return doc.title;
|
433
433
|
});
|
@@ -1,5 +1,4 @@
|
|
1
|
-
import {
|
2
|
-
import { Database, DocWithId, ensureSuperThis, fireproof } from "@fireproof/core";
|
1
|
+
import { Database, DocWithId, fireproof } from "@fireproof/core";
|
3
2
|
|
4
3
|
interface TestDoc {
|
5
4
|
text: string;
|
@@ -9,10 +8,8 @@ interface TestDoc {
|
|
9
8
|
|
10
9
|
describe("query return value consistency", function () {
|
11
10
|
let db: Database;
|
12
|
-
const sthis = ensureSuperThis();
|
13
11
|
|
14
12
|
beforeEach(async () => {
|
15
|
-
await sthis.start();
|
16
13
|
db = fireproof("test-query-docs");
|
17
14
|
|
18
15
|
// Add test documents
|
@@ -28,7 +25,7 @@ describe("query return value consistency", function () {
|
|
28
25
|
|
29
26
|
it("database query should return docs property like useLiveQuery", async function () {
|
30
27
|
// This test should initially fail because the query method doesn't return docs yet
|
31
|
-
const result = await db.query<
|
28
|
+
const result = await db.query<TestDoc>("category");
|
32
29
|
|
33
30
|
// Check that rows property exists (this should pass)
|
34
31
|
expect(result).toHaveProperty("rows");
|
@@ -45,7 +42,7 @@ describe("query return value consistency", function () {
|
|
45
42
|
});
|
46
43
|
|
47
44
|
it("should return docs with the same order as rows", async function () {
|
48
|
-
const result = await db.query<
|
45
|
+
const result = await db.query<TestDoc>("category");
|
49
46
|
|
50
47
|
// Ensure docs array exists
|
51
48
|
expect(result).toHaveProperty("docs");
|
@@ -60,7 +57,7 @@ describe("query return value consistency", function () {
|
|
60
57
|
|
61
58
|
it("should work with complex map functions and query options", async function () {
|
62
59
|
// Test with a map function and query options
|
63
|
-
const result = await db.query<
|
60
|
+
const result = await db.query<TestDoc, boolean>((doc) => doc.active, {
|
64
61
|
key: true,
|
65
62
|
includeDocs: true,
|
66
63
|
});
|
@@ -78,4 +75,42 @@ describe("query return value consistency", function () {
|
|
78
75
|
expect((doc as DocWithId<TestDoc>).active).toBe(true);
|
79
76
|
});
|
80
77
|
});
|
78
|
+
|
79
|
+
it("should only return docs with false value when queried with {key: false}", async function () {
|
80
|
+
// Test with a map function and query options for false value
|
81
|
+
const result = await db.query<TestDoc, boolean>((doc) => doc.active, {
|
82
|
+
key: false,
|
83
|
+
includeDocs: true,
|
84
|
+
});
|
85
|
+
|
86
|
+
// Should only return documents where active is false
|
87
|
+
expect(result.rows.length).toBe(1); // We only have one document with active: false
|
88
|
+
|
89
|
+
// Check docs property exists and matches rows length
|
90
|
+
expect(result).toHaveProperty("docs");
|
91
|
+
expect(result.docs.length).toBe(result.rows.length);
|
92
|
+
|
93
|
+
// Verify all returned docs have active set to false
|
94
|
+
result.docs.forEach((doc) => {
|
95
|
+
expect((doc as DocWithId<TestDoc>).active).toBe(false);
|
96
|
+
});
|
97
|
+
|
98
|
+
// Make sure no documents with active: true are included
|
99
|
+
const activeTrue = result.docs.filter((doc) => (doc as DocWithId<TestDoc>).active === true);
|
100
|
+
expect(activeTrue.length).toBe(0); // No active: true docs should be included
|
101
|
+
|
102
|
+
// Now run a query with key: true for comparison
|
103
|
+
const trueResult = await db.query<TestDoc, boolean>((doc) => doc.active, {
|
104
|
+
key: true,
|
105
|
+
includeDocs: true,
|
106
|
+
});
|
107
|
+
|
108
|
+
// This correctly returns only active: true documents
|
109
|
+
expect(trueResult.rows.length).toBe(2);
|
110
|
+
|
111
|
+
// All returned docs have active set to true
|
112
|
+
trueResult.docs.forEach((doc) => {
|
113
|
+
expect((doc as DocWithId<TestDoc>).active).toBe(true);
|
114
|
+
});
|
115
|
+
});
|
81
116
|
});
|
@@ -0,0 +1,147 @@
|
|
1
|
+
import { describe, it, beforeEach, afterEach, expect } from "vitest";
|
2
|
+
import { Database, fireproof } from "@fireproof/core";
|
3
|
+
|
4
|
+
interface TodoDoc {
|
5
|
+
task: string;
|
6
|
+
completed: boolean;
|
7
|
+
priority?: number;
|
8
|
+
}
|
9
|
+
|
10
|
+
describe("query limit handling", () => {
|
11
|
+
let db: Database;
|
12
|
+
|
13
|
+
beforeEach(async () => {
|
14
|
+
db = await fireproof("test-query-limit");
|
15
|
+
|
16
|
+
// Create multiple documents with different completed values and priorities
|
17
|
+
await db.put({ _id: "task1", task: "Task 1", completed: true, priority: 1 });
|
18
|
+
await db.put({ _id: "task2", task: "Task 2", completed: true, priority: 2 });
|
19
|
+
await db.put({ _id: "task3", task: "Task 3", completed: false, priority: 3 });
|
20
|
+
await db.put({ _id: "task4", task: "Task 4", completed: false, priority: 4 });
|
21
|
+
await db.put({ _id: "task5", task: "Task 5", completed: true, priority: 5 });
|
22
|
+
});
|
23
|
+
|
24
|
+
afterEach(async () => {
|
25
|
+
await db.destroy();
|
26
|
+
});
|
27
|
+
|
28
|
+
// PASSING CASES - These should work correctly with the current implementation
|
29
|
+
|
30
|
+
it("should correctly limit results for regular queries", async () => {
|
31
|
+
// Regular query with limit (no key/keys specified)
|
32
|
+
const queryResult = await db.query("completed", {
|
33
|
+
includeDocs: false,
|
34
|
+
limit: 2,
|
35
|
+
});
|
36
|
+
|
37
|
+
// This should pass - limit should work for regular queries
|
38
|
+
expect(queryResult.rows.length).toBe(2);
|
39
|
+
});
|
40
|
+
|
41
|
+
it("should correctly limit results for 'key' parameter queries", async () => {
|
42
|
+
// Query with a single key and limit
|
43
|
+
const queryResult = await db.query("completed", {
|
44
|
+
key: true,
|
45
|
+
includeDocs: false,
|
46
|
+
limit: 2,
|
47
|
+
});
|
48
|
+
|
49
|
+
// This should pass - limit should work for queries with 'key' option
|
50
|
+
expect(queryResult.rows.length).toBe(2);
|
51
|
+
|
52
|
+
// All results should have completed=true
|
53
|
+
queryResult.rows.forEach((row) => {
|
54
|
+
expect(row.key).toBe(true);
|
55
|
+
});
|
56
|
+
});
|
57
|
+
|
58
|
+
it("should correctly limit range query results", async () => {
|
59
|
+
// Query with range and limit
|
60
|
+
const queryResult = await db.query("priority", {
|
61
|
+
range: [2, 4],
|
62
|
+
includeDocs: false,
|
63
|
+
limit: 2,
|
64
|
+
});
|
65
|
+
|
66
|
+
// This should pass - limit should work for range queries
|
67
|
+
expect(queryResult.rows.length).toBe(2);
|
68
|
+
|
69
|
+
// All results should have priority between 2 and 4
|
70
|
+
queryResult.rows.forEach((row) => {
|
71
|
+
expect(row.key).toBeGreaterThanOrEqual(2);
|
72
|
+
expect(row.key).toBeLessThanOrEqual(4);
|
73
|
+
});
|
74
|
+
});
|
75
|
+
|
76
|
+
// FAILING CASES - These demonstrate the current bug
|
77
|
+
|
78
|
+
it("should respect the limit option with 'keys' parameter (currently failing)", async () => {
|
79
|
+
// Query with multiple keys and limit=1
|
80
|
+
// This should return only 1 result total, but currently returns 1 per key
|
81
|
+
const queryResult = await db.query("completed", {
|
82
|
+
keys: [true, false],
|
83
|
+
includeDocs: false,
|
84
|
+
limit: 1,
|
85
|
+
});
|
86
|
+
|
87
|
+
// This assertion will fail with the current implementation
|
88
|
+
// Current behavior: Returns limit=1 for EACH key, so 2 results total
|
89
|
+
// Expected behavior: Returns limit=1 across ALL keys combined
|
90
|
+
expect(queryResult.rows.length).toBe(1);
|
91
|
+
});
|
92
|
+
|
93
|
+
it("should apply limit correctly to combined results from multiple keys", async () => {
|
94
|
+
// Query with multiple keys and limit=3
|
95
|
+
// Should return exactly 3 results total
|
96
|
+
const queryResult = await db.query<TodoDoc, boolean>("completed", {
|
97
|
+
keys: [true, false],
|
98
|
+
includeDocs: false,
|
99
|
+
limit: 3,
|
100
|
+
});
|
101
|
+
|
102
|
+
// This assertion verifies that limit is applied to the combined result
|
103
|
+
expect(queryResult.rows.length).toBe(3);
|
104
|
+
});
|
105
|
+
|
106
|
+
it("demonstrates the limit+1 issue with the 'keys' parameter", async () => {
|
107
|
+
// Create a controlled test case with exact document counts
|
108
|
+
await db.destroy();
|
109
|
+
db = await fireproof("test-exact-limit");
|
110
|
+
|
111
|
+
// Create exactly 2 documents with completed=true and 2 with completed=false
|
112
|
+
await db.put({ _id: "doc1", task: "Doc 1", completed: true });
|
113
|
+
await db.put({ _id: "doc2", task: "Doc 2", completed: true });
|
114
|
+
await db.put({ _id: "doc3", task: "Doc 3", completed: false });
|
115
|
+
await db.put({ _id: "doc4", task: "Doc 4", completed: false });
|
116
|
+
|
117
|
+
// Query with limit=1 - should return exactly 1 result total
|
118
|
+
const result1 = await db.query("completed", {
|
119
|
+
keys: [true, false],
|
120
|
+
limit: 1,
|
121
|
+
includeDocs: false,
|
122
|
+
});
|
123
|
+
|
124
|
+
// Will fail - returns 2 instead of 1
|
125
|
+
expect(result1.rows.length).toBe(1);
|
126
|
+
|
127
|
+
// Query with limit=2 - should return exactly 2 results total
|
128
|
+
const result2 = await db.query("completed", {
|
129
|
+
keys: [true, false],
|
130
|
+
limit: 2,
|
131
|
+
includeDocs: false,
|
132
|
+
});
|
133
|
+
|
134
|
+
// Will fail - returns 4 instead of 2
|
135
|
+
expect(result2.rows.length).toBe(2);
|
136
|
+
|
137
|
+
// Query with limit=3 - should return exactly 3 results total
|
138
|
+
const result3 = await db.query("completed", {
|
139
|
+
keys: [true, false],
|
140
|
+
limit: 3,
|
141
|
+
includeDocs: false,
|
142
|
+
});
|
143
|
+
|
144
|
+
// Will fail - returns 4 instead of 3
|
145
|
+
expect(result3.rows.length).toBe(3);
|
146
|
+
});
|
147
|
+
});
|
@@ -0,0 +1,89 @@
|
|
1
|
+
import { Database, fireproof } from "@fireproof/core";
|
2
|
+
|
3
|
+
interface TestDoc {
|
4
|
+
text: string;
|
5
|
+
category: string;
|
6
|
+
count: number;
|
7
|
+
}
|
8
|
+
|
9
|
+
describe("query property inconsistency issue", function () {
|
10
|
+
let db: Database;
|
11
|
+
|
12
|
+
beforeEach(async () => {
|
13
|
+
db = fireproof("test-query-property-inconsistency");
|
14
|
+
|
15
|
+
// Add test documents
|
16
|
+
await db.put({ _id: "doc1", text: "hello world", category: "greeting", count: 1 });
|
17
|
+
await db.put({ _id: "doc2", text: "goodbye world", category: "farewell", count: 2 });
|
18
|
+
await db.put({ _id: "doc3", text: "hello again", category: "greeting", count: 3 });
|
19
|
+
});
|
20
|
+
|
21
|
+
afterEach(async () => {
|
22
|
+
await db.close();
|
23
|
+
await db.destroy();
|
24
|
+
});
|
25
|
+
|
26
|
+
it("demonstrates property inconsistency in query results", async function () {
|
27
|
+
// Case 1: Query without key option - should have 'value' property
|
28
|
+
const queryNoKey = await db.query<TestDoc>((doc) => doc.category);
|
29
|
+
|
30
|
+
// Verify it has 'value' property
|
31
|
+
expect(queryNoKey.rows[0]).toHaveProperty("value");
|
32
|
+
|
33
|
+
// Case 2: Query with key option - currently has 'row' property instead of 'value'
|
34
|
+
const queryWithKey = await db.query<TestDoc>((doc) => doc.category, {
|
35
|
+
key: "greeting",
|
36
|
+
});
|
37
|
+
|
38
|
+
// THIS WILL FAIL - Demonstrating the inconsistency
|
39
|
+
// After standardizing on 'value', this assertion should pass
|
40
|
+
expect(queryWithKey.rows[0]).toHaveProperty("value");
|
41
|
+
|
42
|
+
// This assertion will pass after standardizing on 'value' and removing 'row'
|
43
|
+
expect(queryWithKey.rows[0]).not.toHaveProperty("row");
|
44
|
+
});
|
45
|
+
|
46
|
+
it("should use consistent property names regardless of query type", async function () {
|
47
|
+
// Multiple query variations to test different code paths
|
48
|
+
|
49
|
+
// 1. Regular query (no options)
|
50
|
+
const regularQuery = await db.query<TestDoc>((doc) => doc.category);
|
51
|
+
|
52
|
+
// 2. Query with key option
|
53
|
+
const keyQuery = await db.query<TestDoc>((doc) => doc.category, {
|
54
|
+
key: "greeting",
|
55
|
+
});
|
56
|
+
|
57
|
+
// 3. Query with range option
|
58
|
+
const rangeQuery = await db.query<TestDoc>((doc) => doc.count, {
|
59
|
+
range: [1, 3],
|
60
|
+
});
|
61
|
+
|
62
|
+
// 4. Query with prefix option
|
63
|
+
const prefixQuery = await db.query<TestDoc>((doc) => [doc.category, doc.count], {
|
64
|
+
prefix: ["greeting"],
|
65
|
+
});
|
66
|
+
|
67
|
+
// Check each query type has the 'value' property
|
68
|
+
expect(regularQuery.rows[0]).toHaveProperty("value");
|
69
|
+
expect(keyQuery.rows[0]).toHaveProperty("value");
|
70
|
+
expect(rangeQuery.rows[0]).toHaveProperty("value");
|
71
|
+
expect(prefixQuery.rows[0]).toHaveProperty("value");
|
72
|
+
|
73
|
+
// Ensure no query has the 'row' property
|
74
|
+
expect(regularQuery.rows[0]).not.toHaveProperty("row");
|
75
|
+
expect(keyQuery.rows[0]).not.toHaveProperty("row");
|
76
|
+
expect(rangeQuery.rows[0]).not.toHaveProperty("row");
|
77
|
+
expect(prefixQuery.rows[0]).not.toHaveProperty("row");
|
78
|
+
|
79
|
+
// Ensure all queries have the same set of properties
|
80
|
+
const regularProps = Object.keys(regularQuery.rows[0]).sort();
|
81
|
+
const keyProps = Object.keys(keyQuery.rows[0]).sort();
|
82
|
+
const rangeProps = Object.keys(rangeQuery.rows[0]).sort();
|
83
|
+
const prefixProps = Object.keys(prefixQuery.rows[0]).sort();
|
84
|
+
|
85
|
+
expect(keyProps).toEqual(regularProps);
|
86
|
+
expect(rangeProps).toEqual(regularProps);
|
87
|
+
expect(prefixProps).toEqual(regularProps);
|
88
|
+
});
|
89
|
+
});
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import { Database, fireproof } from "@fireproof/core";
|
2
|
+
|
3
|
+
interface TestDoc {
|
4
|
+
text: string;
|
5
|
+
category: string;
|
6
|
+
count: number;
|
7
|
+
}
|
8
|
+
|
9
|
+
describe("query result property consistency", function () {
|
10
|
+
let db: Database;
|
11
|
+
|
12
|
+
beforeEach(async () => {
|
13
|
+
db = fireproof("test-query-result-properties");
|
14
|
+
|
15
|
+
// Add test documents
|
16
|
+
await db.put({ _id: "doc1", text: "hello world", category: "greeting", count: 1 });
|
17
|
+
await db.put({ _id: "doc2", text: "goodbye world", category: "farewell", count: 2 });
|
18
|
+
await db.put({ _id: "doc3", text: "hello again", category: "greeting", count: 3 });
|
19
|
+
});
|
20
|
+
|
21
|
+
afterEach(async () => {
|
22
|
+
await db.close();
|
23
|
+
await db.destroy();
|
24
|
+
});
|
25
|
+
|
26
|
+
it("should have consistent result properties regardless of query options", async function () {
|
27
|
+
// Query without using the key option
|
28
|
+
const resultWithoutKey = await db.query<TestDoc>((doc) => doc.category);
|
29
|
+
|
30
|
+
// Query with the key option
|
31
|
+
const resultWithKey = await db.query<TestDoc>((doc) => doc.category, {
|
32
|
+
key: "greeting",
|
33
|
+
});
|
34
|
+
|
35
|
+
// Add assertions to check property existence
|
36
|
+
const withoutKeyProps = Object.keys(resultWithoutKey.rows[0]);
|
37
|
+
const withKeyProps = Object.keys(resultWithKey.rows[0]);
|
38
|
+
|
39
|
+
// Test if the properties are the same in both cases
|
40
|
+
expect(withoutKeyProps).toEqual(withKeyProps);
|
41
|
+
});
|
42
|
+
});
|