@fireproof/core 0.4.0 → 0.4.1
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/dist/src/fireproof.d.ts +27 -2
- package/dist/src/fireproof.js +2 -1
- package/dist/src/fireproof.js.map +1 -1
- package/dist/src/fireproof.mjs +2 -1
- package/dist/src/fireproof.mjs.map +1 -1
- package/package.json +1 -1
- package/src/database.js +2 -1
- package/dist/blockstore.js +0 -242
- package/dist/clock.js +0 -355
- package/dist/crypto.js +0 -59
- package/dist/database.js +0 -308
- package/dist/db-index.js +0 -314
- package/dist/fireproof.js +0 -83
- package/dist/hooks/use-fireproof.js +0 -100
- package/dist/listener.js +0 -110
- package/dist/main.js +0 -2
- package/dist/main.js.LICENSE.txt +0 -17
- package/dist/prolly.js +0 -316
- package/dist/sha1.js +0 -74
- package/dist/src/blockstore.js +0 -242
- package/dist/src/clock.js +0 -355
- package/dist/src/crypto.js +0 -59
- package/dist/src/database.js +0 -312
- package/dist/src/db-index.js +0 -314
- package/dist/src/index.d.ts +0 -321
- package/dist/src/index.js +0 -38936
- package/dist/src/index.js.map +0 -1
- package/dist/src/index.mjs +0 -38931
- package/dist/src/index.mjs.map +0 -1
- package/dist/src/listener.js +0 -108
- package/dist/src/prolly.js +0 -319
- package/dist/src/sha1.js +0 -74
- package/dist/src/utils.js +0 -16
- package/dist/src/valet.js +0 -262
- package/dist/test/block.js +0 -57
- package/dist/test/clock.test.js +0 -556
- package/dist/test/db-index.test.js +0 -231
- package/dist/test/fireproof.test.js +0 -444
- package/dist/test/fulltext.test.js +0 -61
- package/dist/test/helpers.js +0 -39
- package/dist/test/hydrator.test.js +0 -142
- package/dist/test/listener.test.js +0 -103
- package/dist/test/prolly.test.js +0 -162
- package/dist/test/proofs.test.js +0 -45
- package/dist/test/reproduce-fixture-bug.test.js +0 -57
- package/dist/test/valet.test.js +0 -56
- package/dist/utils.js +0 -16
- package/dist/valet.js +0 -262
@@ -1,231 +0,0 @@
|
|
1
|
-
import { describe, it, beforeEach } from 'mocha';
|
2
|
-
import assert from 'node:assert';
|
3
|
-
import { Fireproof } from '../src/fireproof.js';
|
4
|
-
import { DbIndex } from '../src/db-index.js';
|
5
|
-
console.x = function () { };
|
6
|
-
describe('DbIndex query', () => {
|
7
|
-
let database, index;
|
8
|
-
beforeEach(async () => {
|
9
|
-
database = Fireproof.storage();
|
10
|
-
const docs = [
|
11
|
-
{ _id: 'a1s3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c', name: 'alice', age: 40 },
|
12
|
-
{ _id: 'b2s3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c', name: 'bob', age: 40 },
|
13
|
-
{ _id: 'c3s3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c', name: 'carol', age: 43 },
|
14
|
-
{ _id: 'd4s3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c', name: 'dave', age: 48 },
|
15
|
-
{ _id: 'e4s3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c', name: 'emily', age: 4 },
|
16
|
-
{ _id: 'f4s3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c', name: 'frank', age: 7 }
|
17
|
-
];
|
18
|
-
for (const doc of docs) {
|
19
|
-
const id = doc._id;
|
20
|
-
const response = await database.put(doc);
|
21
|
-
assert(response);
|
22
|
-
assert(response.id, 'should have id');
|
23
|
-
assert.equal(response.id, id);
|
24
|
-
}
|
25
|
-
index = new DbIndex(database, function (doc, map) {
|
26
|
-
map(doc.age, doc.name);
|
27
|
-
}, null, { name: 'namesByAge' });
|
28
|
-
});
|
29
|
-
it('has a name', () => {
|
30
|
-
assert.equal(index.name, 'namesByAge');
|
31
|
-
});
|
32
|
-
it('query index range', async () => {
|
33
|
-
const result = await index.query({ range: [41, 49] });
|
34
|
-
assert(result, 'did return result');
|
35
|
-
assert(result.rows);
|
36
|
-
assert.equal(result.rows.length, 2, 'two row matched');
|
37
|
-
assert.equal(result.rows[0].key, 43);
|
38
|
-
assert(result.rows[0].value === 'carol', 'correct value');
|
39
|
-
});
|
40
|
-
it('query exact key', async () => {
|
41
|
-
let result = await index.query({ range: [41, 44] });
|
42
|
-
assert(result.rows[0].key === 43, 'correct key');
|
43
|
-
result = await index.query({ key: 43 });
|
44
|
-
assert(result, 'did return result');
|
45
|
-
assert(result.rows);
|
46
|
-
assert.equal(result.rows.length, 1, 'one row matched');
|
47
|
-
assert.equal(result.rows[0].key, 43);
|
48
|
-
assert(result.rows[0].value === 'carol', 'correct value');
|
49
|
-
});
|
50
|
-
it('query index all', async () => {
|
51
|
-
const result = await index.query();
|
52
|
-
assert(result, 'did return result');
|
53
|
-
assert(result.rows);
|
54
|
-
assert.equal(result.rows.length, 6, 'six row matched');
|
55
|
-
assert.equal(result.rows[0].key, 4);
|
56
|
-
assert.equal(result.rows[0].value, 'emily');
|
57
|
-
assert.equal(result.rows[result.rows.length - 1].value, 'dave');
|
58
|
-
});
|
59
|
-
it('query index limit', async () => {
|
60
|
-
const result = await index.query({ limit: 3 });
|
61
|
-
assert(result, 'did return result');
|
62
|
-
assert(result.rows);
|
63
|
-
assert.equal(result.rows.length, 3, 'six row matched');
|
64
|
-
assert.equal(result.rows[0].key, 4);
|
65
|
-
assert.equal(result.rows[0].value, 'emily');
|
66
|
-
});
|
67
|
-
it('query index NaN', async () => {
|
68
|
-
const result = await index.query({ range: [NaN, 44] });
|
69
|
-
assert(result, 'did return result');
|
70
|
-
assert(result.rows);
|
71
|
-
assert.equal(result.rows.length, 5, 'six row matched');
|
72
|
-
assert.equal(result.rows[0].key, 4);
|
73
|
-
assert.equal(result.rows[0].value, 'emily');
|
74
|
-
assert.equal(result.rows[result.rows.length - 1].value, 'carol');
|
75
|
-
});
|
76
|
-
it('query index Infinity', async () => {
|
77
|
-
const result = await index.query({ range: [42, Infinity] });
|
78
|
-
assert(result, 'did return result');
|
79
|
-
assert(result.rows);
|
80
|
-
assert.equal(result.rows.length, 2, 'six row matched');
|
81
|
-
assert.equal(result.rows[0].key, 43);
|
82
|
-
assert.equal(result.rows[0].value, 'carol');
|
83
|
-
assert.equal(result.rows[result.rows.length - 1].value, 'dave');
|
84
|
-
});
|
85
|
-
it('query twice', async () => {
|
86
|
-
let result = await index.query({ range: [41, 44] });
|
87
|
-
assert(result, 'did return result');
|
88
|
-
assert(result.rows);
|
89
|
-
assert.equal(result.rows.length, 1, 'one row matched');
|
90
|
-
result = await index.query({ range: [41, 44] });
|
91
|
-
assert(result.rows[0].key === 43, 'correct key');
|
92
|
-
assert(result.rows[0].value === 'carol', 'correct value');
|
93
|
-
});
|
94
|
-
it('query two rows oops', async () => {
|
95
|
-
const result = await index.query({ range: [39, 41] });
|
96
|
-
assert(result, 'did return result');
|
97
|
-
assert(result.rows);
|
98
|
-
assert.equal(result.rows[0].key, 40, 'correct key'); // TODO fix this is currently collating as strings - use gson?
|
99
|
-
assert.equal(result.rows.length, 2, '2 row matched');
|
100
|
-
assert(result.rows[0].value === 'alice', 'correct value');
|
101
|
-
});
|
102
|
-
it('query two rows easy', async () => {
|
103
|
-
const result = await index.query({ range: [40, 41] });
|
104
|
-
assert(result, 'did return result');
|
105
|
-
assert(result.rows);
|
106
|
-
assert.equal(result.rows.length, 2, '2 row matched');
|
107
|
-
assert(result.rows[0].key === 40, 'correct key');
|
108
|
-
assert(result.rows[0].value === 'alice', 'correct value');
|
109
|
-
});
|
110
|
-
it('update index', async () => {
|
111
|
-
const bresult = await index.query({ range: [2, 90] });
|
112
|
-
assert(bresult, 'did return bresult');
|
113
|
-
// console.x('bresult.rows', bresult.rows)
|
114
|
-
assert.equal(bresult.rows.length, 6, 'all row matched');
|
115
|
-
const snapClock = database.clock;
|
116
|
-
const notYet = await database.get('xxxx-3c3a-4b5e-9c1c-8c5c0c5c0c5c').catch((e) => e);
|
117
|
-
assert.equal(notYet.message, 'Not found', 'not yet there');
|
118
|
-
console.x('initial Xander 53', notYet);
|
119
|
-
const response = await database.put({ _id: 'xxxx-3c3a-4b5e-9c1c-8c5c0c5c0c5c', name: 'Xander', age: 53 });
|
120
|
-
assert(response);
|
121
|
-
assert(response.id, 'should have id');
|
122
|
-
const gotX = await database.get(response.id);
|
123
|
-
assert(gotX);
|
124
|
-
assert(gotX.name === 'Xander', 'got Xander');
|
125
|
-
console.x('got X');
|
126
|
-
const snap = Fireproof.snapshot(database, snapClock);
|
127
|
-
const aliceOld = await snap.get('a1s3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c'); // .catch((e) => e)
|
128
|
-
console.x('aliceOld', aliceOld);
|
129
|
-
assert.equal(aliceOld.name, 'alice', 'alice old');
|
130
|
-
const noX = await snap.get(response.id).catch((e) => e);
|
131
|
-
assert.equal(noX.message, 'Not found', 'not yet there');
|
132
|
-
const allresult = await index.query({ range: [2, 90] });
|
133
|
-
assert.equal(allresult.rows.length, 7, 'all row matched');
|
134
|
-
const result = await index.query({ range: [51, 54] });
|
135
|
-
assert(result, 'did return result');
|
136
|
-
assert(result.rows);
|
137
|
-
assert.equal(result.rows.length, 1, '1 row matched');
|
138
|
-
assert(result.rows[0].key === 53, 'correct key');
|
139
|
-
});
|
140
|
-
it('update index with document update to different key', async () => {
|
141
|
-
await index.query({ range: [51, 54] });
|
142
|
-
console.x('--- make Xander 53');
|
143
|
-
const DOCID = 'xander-doc';
|
144
|
-
const r1 = await database.put({ _id: DOCID, name: 'Xander', age: 53 });
|
145
|
-
assert(r1.id, 'should have id');
|
146
|
-
const result = await index.query({ range: [51, 54] });
|
147
|
-
assert(result, 'did return result');
|
148
|
-
assert(result.rows);
|
149
|
-
console.x('result.rows', result.rows);
|
150
|
-
assert.equal(result.rows.length, 1, '1 row matched');
|
151
|
-
assert(result.rows[0].key === 53, 'correct key');
|
152
|
-
const snap = Fireproof.snapshot(database);
|
153
|
-
console.x('--- make Xander 63');
|
154
|
-
const response = await database.put({ _id: DOCID, name: 'Xander', age: 63 });
|
155
|
-
assert(response);
|
156
|
-
assert(response.id, 'should have id');
|
157
|
-
const oldXander = await snap.get(r1.id);
|
158
|
-
assert.equal(oldXander.age, 53, 'old xander');
|
159
|
-
// console.x('--- test snapshot', snap.clock)
|
160
|
-
const newZander = await database.get(r1.id);
|
161
|
-
assert.equal(newZander.age, 63, 'new xander');
|
162
|
-
// console.x('--- test liveshot', database.clock)
|
163
|
-
const result2 = await index.query({ range: [61, 64] });
|
164
|
-
assert(result2, 'did return result');
|
165
|
-
assert(result2.rows);
|
166
|
-
assert.equal(result2.rows.length, 1, '1 row matched');
|
167
|
-
assert(result2.rows[0].key === 63, 'correct key');
|
168
|
-
const resultempty = await index.query({ range: [51, 54] });
|
169
|
-
assert(resultempty, 'did return resultempty');
|
170
|
-
assert(resultempty.rows);
|
171
|
-
console.x('resultempty.rows', resultempty.rows);
|
172
|
-
assert(resultempty.rows.length === 0, 'old Xander should be gone');
|
173
|
-
const allresult = await index.query({ range: [2, 90] });
|
174
|
-
console.x('allresult.rows', allresult.rows);
|
175
|
-
// todo
|
176
|
-
assert.equal(allresult.rows.length, 7, 'all row matched');
|
177
|
-
});
|
178
|
-
it('update index with document deletion', async () => {
|
179
|
-
await index.query({ range: [51, 54] });
|
180
|
-
console.x('--- make Xander 53');
|
181
|
-
const DOCID = 'xxxx-3c3a-4b5e-9c1c-8c5c0c5c0c5c';
|
182
|
-
const r1 = await database.put({ _id: DOCID, name: 'Xander', age: 53 });
|
183
|
-
assert(r1.id, 'should have id');
|
184
|
-
const result = await index.query({ range: [51, 54] });
|
185
|
-
assert(result, 'did return result');
|
186
|
-
assert(result.rows);
|
187
|
-
console.x('result.rows', result.rows);
|
188
|
-
assert.equal(result.rows.length, 1, '1 row matched');
|
189
|
-
assert(result.rows[0].key === 53, 'correct key');
|
190
|
-
const snap = Fireproof.snapshot(database);
|
191
|
-
console.x('--- delete Xander 53');
|
192
|
-
const response = await database.del(DOCID);
|
193
|
-
assert(response);
|
194
|
-
assert(response.id, 'should have id');
|
195
|
-
const oldXander = await snap.get(r1.id);
|
196
|
-
assert.equal(oldXander.age, 53, 'old xander');
|
197
|
-
// console.x('--- test snapshot', snap.clock)
|
198
|
-
const newZander = await database.get(r1.id).catch((e) => e);
|
199
|
-
assert.equal(newZander.message, 'Not found', 'new xander');
|
200
|
-
// console.x('--- test liveshot', database.clock)
|
201
|
-
const allresult = await index.query({ range: [2, 90] });
|
202
|
-
console.x('allresult.rows', allresult.rows);
|
203
|
-
// todo
|
204
|
-
assert.equal(allresult.rows.length, 6, 'all row matched');
|
205
|
-
const result2 = await index.query({ range: [51, 54] });
|
206
|
-
assert(result2, 'did return result');
|
207
|
-
assert(result2.rows);
|
208
|
-
assert.equal(result2.rows.length, 0, '0 row matched');
|
209
|
-
});
|
210
|
-
});
|
211
|
-
describe('DbIndex query with bad index definition', () => {
|
212
|
-
let database, index;
|
213
|
-
beforeEach(async () => {
|
214
|
-
database = Fireproof.storage();
|
215
|
-
await database.put({ _id: 'a1s3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c', name: 'alice', age: 40 });
|
216
|
-
index = new DbIndex(database, function (doc, map) {
|
217
|
-
map(doc.oops.missingField, doc.name);
|
218
|
-
});
|
219
|
-
});
|
220
|
-
it('has a default name', () => {
|
221
|
-
assert.equal(index.name, 'doc.oops.missingField, doc.name');
|
222
|
-
});
|
223
|
-
it('query index range', async () => {
|
224
|
-
const oldErrFn = console.error;
|
225
|
-
console.error = () => { };
|
226
|
-
await index.query({ range: [41, 44] }).catch((e) => {
|
227
|
-
assert(/missingField/.test(e.message));
|
228
|
-
console.error = oldErrFn;
|
229
|
-
});
|
230
|
-
});
|
231
|
-
});
|
@@ -1,444 +0,0 @@
|
|
1
|
-
import { describe, it, beforeEach } from 'mocha';
|
2
|
-
import assert from 'node:assert';
|
3
|
-
import { Fireproof } from '../src/fireproof.js';
|
4
|
-
// import * as codec from '@ipld/dag-cbor'
|
5
|
-
let database, resp0;
|
6
|
-
// const sleep = (ms) => new Promise((r) => setTimeout(r, ms))
|
7
|
-
describe('Fireproof', () => {
|
8
|
-
beforeEach(async () => {
|
9
|
-
database = Fireproof.storage('helloName');
|
10
|
-
resp0 = await database.put({
|
11
|
-
_id: '1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c',
|
12
|
-
name: 'alice',
|
13
|
-
age: 42
|
14
|
-
});
|
15
|
-
});
|
16
|
-
it('takes an optional name', () => {
|
17
|
-
assert.equal(database.name, 'helloName');
|
18
|
-
const km = database.blocks.valet.getKeyMaterial();
|
19
|
-
if (process.env.NO_ENCRYPT) {
|
20
|
-
assert.equal(km, null);
|
21
|
-
}
|
22
|
-
else {
|
23
|
-
assert.equal(km.length, 64);
|
24
|
-
}
|
25
|
-
const x = database.blocks.valet.idb;
|
26
|
-
const keyId = database.blocks.valet.keyId;
|
27
|
-
assert.equal(x.name.toString(), `fp.${keyId}.helloName.valet`);
|
28
|
-
});
|
29
|
-
it('only put and get document', async () => {
|
30
|
-
assert(resp0.id, 'should have id');
|
31
|
-
assert.equal(resp0.id, '1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c');
|
32
|
-
const avalue = await database.get('1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c');
|
33
|
-
assert.equal(avalue.name, 'alice');
|
34
|
-
assert.equal(avalue.age, 42);
|
35
|
-
assert.equal(avalue._id, '1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c');
|
36
|
-
});
|
37
|
-
it('mvcc put and get document with _clock that matches', async () => {
|
38
|
-
assert(resp0.clock, 'should have clock');
|
39
|
-
assert.equal(resp0.clock[0].toString(), 'bafyreiadhnnxgaeeqdxujfew6zxr4lnjyskkrg26cdjvk7tivy6dt4xmsm');
|
40
|
-
const theDoc = await database.get('1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c');
|
41
|
-
theDoc._clock = database.clock;
|
42
|
-
const put2 = await database.put(theDoc);
|
43
|
-
assert.equal(put2.id, '1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c');
|
44
|
-
assert.equal(put2.clock.length, 1);
|
45
|
-
assert.equal(put2.clock[0].toString(), 'bafyreib2kck2fv73lgahfcd5imarslgxcmachbxxavhtwahx5ppjfts4qe');
|
46
|
-
});
|
47
|
-
it('get should return an object instance that is not the same as the one in the db', async () => {
|
48
|
-
const theDoc = await database.get('1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c');
|
49
|
-
const theDoc2 = await database.get('1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c');
|
50
|
-
assert.notEqual(theDoc, theDoc2);
|
51
|
-
theDoc.name = 'really alice';
|
52
|
-
assert.equal(theDoc.name, 'really alice');
|
53
|
-
assert.equal(theDoc2.name, 'alice');
|
54
|
-
});
|
55
|
-
it('get with mvcc option', async () => {
|
56
|
-
const theDoc = await database.get('1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c', { mvcc: true });
|
57
|
-
assert(theDoc._clock, 'should have _clock');
|
58
|
-
assert.equal(theDoc._clock[0].toString(), 'bafyreiadhnnxgaeeqdxujfew6zxr4lnjyskkrg26cdjvk7tivy6dt4xmsm');
|
59
|
-
});
|
60
|
-
it('get with mvcc option where someone else changed another document first', async () => {
|
61
|
-
const theDoc = await database.get('1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c', { mvcc: true });
|
62
|
-
const put2 = await database.put({ something: 'else' });
|
63
|
-
assert(put2.clock, 'should have clock');
|
64
|
-
assert.notEqual(put2.clock.toString(), resp0.clock.toString());
|
65
|
-
assert.equal(theDoc._clock.toString(), resp0.clock.toString());
|
66
|
-
theDoc.name = 'somone else';
|
67
|
-
const put3works = await database.put(theDoc);
|
68
|
-
assert(put3works.clock, 'should have id');
|
69
|
-
});
|
70
|
-
it('get from an old snapshot with mvcc option', async () => {
|
71
|
-
const ogClock = resp0.clock;
|
72
|
-
const theDoc = await database.get('1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c');
|
73
|
-
theDoc.name = 'not alice';
|
74
|
-
const put2 = await database.put(theDoc);
|
75
|
-
assert.equal(put2.id, '1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c');
|
76
|
-
assert.notEqual(put2.clock.toString(), ogClock.toString());
|
77
|
-
const theDoc2 = await database.get('1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c', { clock: ogClock });
|
78
|
-
assert.equal(theDoc2.name, 'alice');
|
79
|
-
});
|
80
|
-
it('put and get document with _clock that does not match b/c the doc changed', async () => {
|
81
|
-
const theDoc = await database.get('1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c', { mvcc: true });
|
82
|
-
theDoc.name = 'not alice';
|
83
|
-
const put2 = await database.put(theDoc);
|
84
|
-
assert.equal(put2.id, '1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c');
|
85
|
-
assert.notEqual(put2.clock.toString(), theDoc._clock.toString());
|
86
|
-
const err = await database.put(theDoc).catch((err) => err);
|
87
|
-
assert.match(err.message, /MVCC conflict/);
|
88
|
-
});
|
89
|
-
it('put and get document with _clock that does not match b/c a different doc changed should succeed', async () => {
|
90
|
-
const theDoc = await database.get('1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c', { mvcc: true });
|
91
|
-
assert.equal(theDoc.name, 'alice');
|
92
|
-
const putAnotherDoc = await database.put({ nothing: 'to see here' });
|
93
|
-
assert.notEqual(putAnotherDoc.clock.toString(), theDoc._clock.toString());
|
94
|
-
const ok = await database.put({ name: "isn't alice", ...theDoc });
|
95
|
-
assert.equal(ok.id, '1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c');
|
96
|
-
});
|
97
|
-
it('put and get document with _clock that does not match b/c the doc was deleted', async () => {
|
98
|
-
const theDoc = await database.get('1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c', { mvcc: true });
|
99
|
-
assert.equal(theDoc.name, 'alice');
|
100
|
-
const del = await database.del(theDoc);
|
101
|
-
assert(del.id);
|
102
|
-
const err = await database.put(theDoc).catch((err) => err);
|
103
|
-
console.log('err', err);
|
104
|
-
assert.match(err.message, /MVCC conflict/);
|
105
|
-
});
|
106
|
-
it('allDocuments', async () => {
|
107
|
-
await database.put({ name: 'bob' });
|
108
|
-
const allDocs = await database.allDocuments();
|
109
|
-
assert.equal(allDocs.rows.length, 2);
|
110
|
-
});
|
111
|
-
it('has a factory for making new instances with default settings', async () => {
|
112
|
-
// TODO if you pass it an email it asks the local keyring, and if no key, does the email validation thing
|
113
|
-
const db = await Fireproof.storage('test');
|
114
|
-
assert.equal(db.name, 'test');
|
115
|
-
});
|
116
|
-
it('an empty database has no documents', async () => {
|
117
|
-
const db = Fireproof.storage();
|
118
|
-
const e = await db.get('8c5c0c5c0c5c').catch((err) => err);
|
119
|
-
assert.equal(e.message, 'Not found');
|
120
|
-
const changes = await db.changesSince();
|
121
|
-
assert.equal(changes.rows.length, 0);
|
122
|
-
});
|
123
|
-
it('delete on an empty database', async () => {
|
124
|
-
const db = Fireproof.storage();
|
125
|
-
const e = await db.del('8c5c0c5c0c5c').catch((err) => err);
|
126
|
-
assert.equal(e.id, '8c5c0c5c0c5c');
|
127
|
-
const changes = await db.changesSince();
|
128
|
-
assert.equal(changes.rows.length, 0);
|
129
|
-
});
|
130
|
-
it('update existing document', async () => {
|
131
|
-
// const alice = await database.get('1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c')
|
132
|
-
// assert.equal(alice.name, 'alice')
|
133
|
-
const dogKey = 'aster-3c3a-4b5e-9c1c-8c5c0c5c0c5c';
|
134
|
-
const value = {
|
135
|
-
_id: dogKey,
|
136
|
-
name: 'aster',
|
137
|
-
age: 2
|
138
|
-
};
|
139
|
-
const response = await database.put(value);
|
140
|
-
assert(response.id, 'should have id');
|
141
|
-
assert.equal(response.id, dogKey);
|
142
|
-
assert.equal(value._id, dogKey);
|
143
|
-
const snapshot = Fireproof.snapshot(database);
|
144
|
-
const avalue = await database.get(dogKey);
|
145
|
-
assert.equal(avalue.name, value.name);
|
146
|
-
assert.equal(avalue.age, value.age);
|
147
|
-
assert.equal(avalue._id, dogKey);
|
148
|
-
avalue.age = 3;
|
149
|
-
const response2 = await database.put(avalue);
|
150
|
-
assert(response2.id, 'should have id');
|
151
|
-
assert.equal(response2.id, dogKey);
|
152
|
-
const bvalue = await database.get(dogKey);
|
153
|
-
assert.equal(bvalue.name, value.name);
|
154
|
-
assert.equal(bvalue.age, 3);
|
155
|
-
assert.equal(bvalue._id, dogKey);
|
156
|
-
const snapdoc = await snapshot.get(dogKey);
|
157
|
-
// console.log('snapdoc', snapdoc)
|
158
|
-
// assert(snapdoc.id, 'should have id')
|
159
|
-
assert.equal(snapdoc._id, dogKey);
|
160
|
-
assert.equal(snapdoc.age, 2);
|
161
|
-
});
|
162
|
-
it("update document with validation function that doesn't allow it", async () => {
|
163
|
-
const validationDatabase = Fireproof.storage('validation', {
|
164
|
-
validateChange: (newDoc, oldDoc, authCtx) => {
|
165
|
-
if (newDoc.name === 'bob') {
|
166
|
-
throw new Error('no bobs allowed');
|
167
|
-
}
|
168
|
-
}
|
169
|
-
});
|
170
|
-
const validResp = await validationDatabase.put({
|
171
|
-
_id: '111-alice',
|
172
|
-
name: 'alice',
|
173
|
-
age: 42
|
174
|
-
});
|
175
|
-
const getResp = await validationDatabase.get(validResp.id);
|
176
|
-
assert.equal(getResp.name, 'alice');
|
177
|
-
let e = await validationDatabase
|
178
|
-
.put({
|
179
|
-
_id: '222-bob',
|
180
|
-
name: 'bob',
|
181
|
-
age: 11
|
182
|
-
})
|
183
|
-
.catch((e) => e);
|
184
|
-
assert.equal(e.message, 'no bobs allowed');
|
185
|
-
e = await validationDatabase.get('222-bob').catch((e) => e);
|
186
|
-
assert.equal(e.message, 'Not found');
|
187
|
-
});
|
188
|
-
it('get missing document', async () => {
|
189
|
-
const e = await database.get('missing').catch((e) => e);
|
190
|
-
assert.equal(e.message, 'Not found');
|
191
|
-
});
|
192
|
-
it('delete the only document', async () => {
|
193
|
-
const id = '1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c';
|
194
|
-
const found = await database.get(id);
|
195
|
-
assert.equal(found._id, id);
|
196
|
-
const deleted = await database.del(id);
|
197
|
-
assert.equal(deleted.id, id);
|
198
|
-
const e = await database
|
199
|
-
.get(id)
|
200
|
-
.then((doc) => assert.equal('should be deleted', JSON.stringify(doc)))
|
201
|
-
.catch((e) => {
|
202
|
-
if (e.message !== 'Not found') {
|
203
|
-
throw e;
|
204
|
-
}
|
205
|
-
return e;
|
206
|
-
});
|
207
|
-
assert.equal(e.message, 'Not found');
|
208
|
-
});
|
209
|
-
it('delete not last document', async () => {
|
210
|
-
const resp1 = await database.put({
|
211
|
-
_id: 'second',
|
212
|
-
name: 'bob',
|
213
|
-
age: 39
|
214
|
-
});
|
215
|
-
// const id = '1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c'
|
216
|
-
const id = resp1.id;
|
217
|
-
const found = await database.get(id);
|
218
|
-
assert.equal(found._id, id);
|
219
|
-
const deleted = await database.del(id);
|
220
|
-
assert.equal(deleted.id, id);
|
221
|
-
const e = await database
|
222
|
-
.get(id)
|
223
|
-
.then((doc) => assert.equal('should be deleted', JSON.stringify(doc)))
|
224
|
-
.catch((e) => {
|
225
|
-
if (e.message !== 'Not found') {
|
226
|
-
throw e;
|
227
|
-
}
|
228
|
-
return e;
|
229
|
-
});
|
230
|
-
assert.equal(e.message, 'Not found');
|
231
|
-
});
|
232
|
-
it("delete a document with validation function that doesn't allow it", async () => {
|
233
|
-
const validationDatabase = Fireproof.storage('validation', {
|
234
|
-
validateChange: (newDoc, oldDoc, authCtx) => {
|
235
|
-
if (oldDoc.name === 'bob') {
|
236
|
-
throw new Error('no changing bob');
|
237
|
-
}
|
238
|
-
}
|
239
|
-
});
|
240
|
-
const validResp = await validationDatabase.put({
|
241
|
-
_id: '222-bob',
|
242
|
-
name: 'bob',
|
243
|
-
age: 11
|
244
|
-
});
|
245
|
-
const getResp = await validationDatabase.get(validResp.id);
|
246
|
-
assert.equal(getResp.name, 'bob');
|
247
|
-
const e = await validationDatabase
|
248
|
-
.put({
|
249
|
-
_id: '222-bob',
|
250
|
-
name: 'bob',
|
251
|
-
age: 12
|
252
|
-
})
|
253
|
-
.catch((e) => e);
|
254
|
-
assert.equal(e.message, 'no changing bob');
|
255
|
-
let prevBob = await validationDatabase.get('222-bob');
|
256
|
-
assert.equal(prevBob.name, 'bob');
|
257
|
-
assert.equal(prevBob.age, 11);
|
258
|
-
const e2 = await validationDatabase.del('222-bob').catch((e) => e);
|
259
|
-
assert.equal(e2.message, 'no changing bob');
|
260
|
-
prevBob = await validationDatabase.get('222-bob');
|
261
|
-
assert.equal(prevBob.name, 'bob');
|
262
|
-
assert.equal(prevBob.age, 11);
|
263
|
-
});
|
264
|
-
it('provides docs since tiny', async () => {
|
265
|
-
const result = await database.changesSince();
|
266
|
-
assert.equal(result.rows.length, 1);
|
267
|
-
assert.equal(result.rows[0].key, '1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c');
|
268
|
-
// console.log('result', result)
|
269
|
-
// const result2 = await database.changesSince(result.clock)
|
270
|
-
// console.log('result2', result2)
|
271
|
-
// assert.equal(result2.rows.length, 0)
|
272
|
-
const bKey = 'befbef-3c3a-4b5e-9c1c-bbbbbb';
|
273
|
-
const bvalue = {
|
274
|
-
_id: bKey,
|
275
|
-
name: 'bob',
|
276
|
-
age: 44
|
277
|
-
};
|
278
|
-
const response = await database.put(bvalue);
|
279
|
-
assert(response.id, 'should have id');
|
280
|
-
assert.equal(response.id, bKey);
|
281
|
-
const res3 = await database.changesSince();
|
282
|
-
assert.equal(res3.rows.length, 2);
|
283
|
-
const res4 = await database.changesSince(result.clock);
|
284
|
-
assert.equal(res4.rows.length, 1);
|
285
|
-
});
|
286
|
-
it('provides docs since', async () => {
|
287
|
-
const result = await database.changesSince();
|
288
|
-
assert.equal(result.rows.length, 1);
|
289
|
-
assert.equal(result.rows[0].key, '1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c');
|
290
|
-
const result2 = await database.changesSince(result.clock);
|
291
|
-
assert.equal(result2.rows.length, 0);
|
292
|
-
const bKey = 'befbef-3c3a-4b5e-9c1c-bbbbbb';
|
293
|
-
const bvalue = {
|
294
|
-
_id: bKey,
|
295
|
-
name: 'bob',
|
296
|
-
age: 44
|
297
|
-
};
|
298
|
-
const response = await database.put(bvalue);
|
299
|
-
assert(response.id, 'should have id');
|
300
|
-
assert.equal(response.id, bKey);
|
301
|
-
const res3 = await database.changesSince(result2.clock);
|
302
|
-
assert.equal(res3.rows.length, 1);
|
303
|
-
const res4 = await database.changesSince(res3.clock);
|
304
|
-
assert.equal(res4.rows.length, 0);
|
305
|
-
assert.equal(res4.clock[0], res3.clock[0]);
|
306
|
-
assert.equal(res4.clock.length, res3.clock.length);
|
307
|
-
const cKey = 'cefecef-3c3a-4b5e-9c1c-bbbbbb';
|
308
|
-
const value = {
|
309
|
-
_id: cKey,
|
310
|
-
name: 'carol',
|
311
|
-
age: 44
|
312
|
-
};
|
313
|
-
const response2 = await database.put(value);
|
314
|
-
assert(response2.id, 'should have id');
|
315
|
-
assert.equal(response2.id, cKey);
|
316
|
-
const res5 = await database.changesSince(res4.clock);
|
317
|
-
assert.equal(res5.rows.length, 1);
|
318
|
-
const res6 = await database.changesSince(result2.clock);
|
319
|
-
assert.equal(res6.rows.length, 2);
|
320
|
-
const resultAll = await database.changesSince();
|
321
|
-
assert.equal(resultAll.rows.length, 3);
|
322
|
-
assert.equal(resultAll.rows[0].key, '1ef3b32a-3c3a-4b5e-9c1c-8c5c0c5c0c5c');
|
323
|
-
const res7 = await database.changesSince(resultAll.clock);
|
324
|
-
assert.equal(res7.rows.length, 0);
|
325
|
-
const valueCupdate = {
|
326
|
-
_id: cKey,
|
327
|
-
name: 'carol update',
|
328
|
-
age: 45
|
329
|
-
};
|
330
|
-
const responseUpdate = await database.put(valueCupdate);
|
331
|
-
assert(responseUpdate.id);
|
332
|
-
const res8 = await database.changesSince(resultAll.clock);
|
333
|
-
assert.equal(res8.rows.length, 1);
|
334
|
-
const res9 = await database.changesSince(res8.clock);
|
335
|
-
assert.equal(res9.rows.length, 0);
|
336
|
-
});
|
337
|
-
it('docs since repeated changes', async () => {
|
338
|
-
assert.equal((await database.changesSince()).rows.length, 1);
|
339
|
-
let resp, doc, changes;
|
340
|
-
for (let index = 0; index < 30; index++) {
|
341
|
-
const id = '1' + (301 - index).toString();
|
342
|
-
// console.log(`Putting id: ${id}, index: ${index}`)
|
343
|
-
resp = await database.put({ index, _id: id }).catch(e => {
|
344
|
-
assert.fail(`put failed on _id: ${id}, error: ${e.message}`);
|
345
|
-
});
|
346
|
-
assert(resp.id, `Failed to obtain resp.id for _id: ${id}`);
|
347
|
-
// console.log(`vis for update id: ${id}, index:`, index)
|
348
|
-
// for await (const line of database.vis()) {
|
349
|
-
// console.log(line)
|
350
|
-
// }
|
351
|
-
doc = await database.get(resp.id).catch(e => {
|
352
|
-
console.log('failed', e);
|
353
|
-
assert.fail(`get failed on _id: ${id}, error: ${e.message}`);
|
354
|
-
});
|
355
|
-
assert.equal(doc.index, index, `doc.index is not equal to index for _id: ${id}`);
|
356
|
-
changes = await database.changesSince().catch(async (e) => {
|
357
|
-
assert.fail(`changesSince failed on _id: ${id}, error: ${e.message}`);
|
358
|
-
});
|
359
|
-
changes.rows.forEach(row => {
|
360
|
-
for (const key in row) {
|
361
|
-
const value = row[key];
|
362
|
-
assert(!/^bafy/.test(value), `Unexpected "bafy..." value found at index ${index} in row ${JSON.stringify(row)}`);
|
363
|
-
}
|
364
|
-
});
|
365
|
-
database.blocks.clearCommittedCache(); // clear cache to force re-reading from encrypted store
|
366
|
-
doc = await database.get(resp.id).catch(e => {
|
367
|
-
console.log('failed', e);
|
368
|
-
assert.fail(`get failed on _id: ${id}, error: ${e.message}`);
|
369
|
-
});
|
370
|
-
assert.equal(doc.index, index, `doc.index is not equal to index for _id: ${id}`);
|
371
|
-
changes = await database.changesSince().catch(async (e) => {
|
372
|
-
assert.fail(`changesSince failed on _id: ${id}, error: ${e.message}`);
|
373
|
-
});
|
374
|
-
changes.rows.forEach(row => {
|
375
|
-
for (const key in row) {
|
376
|
-
const value = row[key];
|
377
|
-
assert(!/^bafy/.test(value), `Unexpected "bafy..." value found at index ${index} in row ${JSON.stringify(row)}`);
|
378
|
-
}
|
379
|
-
});
|
380
|
-
// console.log('changes: ', index, changes.rows.length, JSON.stringify(changes.rows))
|
381
|
-
assert.equal(changes.rows.length, index + 2, `failed on ${index}, with ${changes.rows.length} ${id}`);
|
382
|
-
}
|
383
|
-
}).timeout(30000);
|
384
|
-
it('concurrent transactions', async () => {
|
385
|
-
assert.equal((await database.changesSince()).rows.length, 1);
|
386
|
-
const promises = [];
|
387
|
-
let putYes = 0;
|
388
|
-
for (let index = 0; index < 20; index++) {
|
389
|
-
const id = 'a' + (300 - index).toString();
|
390
|
-
promises.push(database.put({ index, _id: id }).catch(e => {
|
391
|
-
assert.equal(e.message, 'put failed on _id: ' + id);
|
392
|
-
}).then(r => {
|
393
|
-
if (r.id) {
|
394
|
-
putYes++;
|
395
|
-
return database.get(r.id).catch(e => {
|
396
|
-
// assert.equal(e.message, 'get failed on _id: ' + r.id)
|
397
|
-
}).then(d => {
|
398
|
-
// assert.equal(d.index, index)
|
399
|
-
return r.id;
|
400
|
-
});
|
401
|
-
}
|
402
|
-
}));
|
403
|
-
promises.push(database.changesSince().catch(e => {
|
404
|
-
assert.equal(e.message, 'changesSince failed');
|
405
|
-
}).then(c => {
|
406
|
-
assert(c.rows.length > 0);
|
407
|
-
return c.rows.length;
|
408
|
-
}));
|
409
|
-
}
|
410
|
-
const got = await Promise.all(promises);
|
411
|
-
assert.equal(got.length, putYes * 2);
|
412
|
-
// console.log('putYes', putYes)
|
413
|
-
// await sleep(1000)
|
414
|
-
assert.equal((await database.changesSince()).rows.length, 2);
|
415
|
-
}).timeout(20000);
|
416
|
-
it('serialize database', async () => {
|
417
|
-
await database.put({ _id: 'rehy', name: 'drate' });
|
418
|
-
assert.equal((await database.changesSince()).rows.length, 2);
|
419
|
-
const serialized = JSON.parse(JSON.stringify(database));
|
420
|
-
assert.equal(serialized.name, 'helloName');
|
421
|
-
assert.equal(serialized.clock.length, 1);
|
422
|
-
});
|
423
|
-
it('clocked changes in order', async () => {
|
424
|
-
await database.put({ _id: '2' });
|
425
|
-
await database.put({ _id: 'three' });
|
426
|
-
await database.put({ _id: '4' });
|
427
|
-
const changes = await database.changesSince(resp0.clock);
|
428
|
-
assert.equal(changes.rows.length, 3);
|
429
|
-
assert.equal(changes.rows[0].key, '2');
|
430
|
-
assert.equal(changes.rows[1].key, 'three');
|
431
|
-
assert.equal(changes.rows[2].key, '4');
|
432
|
-
});
|
433
|
-
it.skip('changes in order', async () => {
|
434
|
-
await database.put({ _id: '2' });
|
435
|
-
await database.put({ _id: 'three' });
|
436
|
-
await database.put({ _id: '4' });
|
437
|
-
const changes = await database.changesSince();
|
438
|
-
assert.equal(changes.rows.length, 4);
|
439
|
-
assert.equal(changes.rows[0].key, resp0.id);
|
440
|
-
assert.equal(changes.rows[1].key, '2');
|
441
|
-
assert.equal(changes.rows[2].key, 'three');
|
442
|
-
assert.equal(changes.rows[3].key, '4');
|
443
|
-
});
|
444
|
-
});
|