@fireproof/core 0.16.7 → 0.17.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +15 -6
- package/dist/browser/fireproof.cjs +62 -56
- package/dist/browser/fireproof.cjs.map +1 -1
- package/dist/browser/fireproof.d.cts +4 -4
- package/dist/browser/fireproof.d.ts +4 -4
- package/dist/browser/fireproof.global.js +713 -275
- package/dist/browser/fireproof.global.js.map +1 -1
- package/dist/browser/fireproof.js +64 -58
- package/dist/browser/fireproof.js.map +1 -1
- package/dist/browser/metafile-cjs.json +1 -1
- package/dist/browser/metafile-esm.json +1 -1
- package/dist/browser/metafile-iife.json +1 -1
- package/dist/memory/fireproof.cjs +62 -56
- package/dist/memory/fireproof.cjs.map +1 -1
- package/dist/memory/fireproof.d.cts +4 -4
- package/dist/memory/fireproof.d.ts +4 -4
- package/dist/memory/fireproof.global.js +713 -275
- package/dist/memory/fireproof.global.js.map +1 -1
- package/dist/memory/fireproof.js +64 -58
- package/dist/memory/fireproof.js.map +1 -1
- package/dist/memory/metafile-cjs.json +1 -1
- package/dist/memory/metafile-esm.json +1 -1
- package/dist/memory/metafile-iife.json +1 -1
- package/dist/node/fireproof.cjs +62 -56
- package/dist/node/fireproof.cjs.map +1 -1
- package/dist/node/fireproof.d.cts +4 -4
- package/dist/node/fireproof.d.ts +4 -4
- package/dist/node/fireproof.global.js +713 -275
- package/dist/node/fireproof.global.js.map +1 -1
- package/dist/node/fireproof.js +64 -58
- package/dist/node/fireproof.js.map +1 -1
- package/dist/node/metafile-cjs.json +1 -1
- package/dist/node/metafile-esm.json +1 -1
- package/dist/node/metafile-iife.json +1 -1
- package/package.json +4 -7
package/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
|
2
2
|
|
3
|
-
# <img src="https://fireproof.storage/static/img/flame.svg" alt="Fireproof logo" width="25"> Fireproof
|
3
|
+
# <img src="https://fireproof.storage/static/img/flame.svg" alt="Fireproof logo" width="25"> [Fireproof](https://fireproof.storage) – live database for the web
|
4
4
|
|
5
5
|
<p align="right">
|
6
6
|
<a href="https://github.com/fireproof-storage/fireproof/actions/workflows/test.yml">
|
@@ -10,7 +10,11 @@
|
|
10
10
|
|
11
11
|
Simplify your application state with a live database. Automatically update your UI based on local or remote changes, and optionally integrate with any cloud for replication and sharing.
|
12
12
|
|
13
|
-
Fireproof is an embedded JavaScript document database designed to streamline app development. Data resides locally, with optional encrypted cloud storage and
|
13
|
+
Fireproof is an embedded JavaScript document database designed to streamline app development. Data resides locally, with optional encrypted cloud storage and real-time sync and collaboration. Features like live queries, database branches and snapshots, and file attachments make Fireproof ideal for browser-based apps big or small.
|
14
|
+
|
15
|
+
Fireproof works in the browser, server, edge function, and any other JavaScript environment, with [connectors for popular backend services like AWS, Netlify, and PartyKit.]()
|
16
|
+
|
17
|
+
### Install Anywhere
|
14
18
|
|
15
19
|
Get started with just the NPM module:
|
16
20
|
|
@@ -24,13 +28,19 @@ or target specific builds via:
|
|
24
28
|
npm install @fireproof/core
|
25
29
|
```
|
26
30
|
|
27
|
-
|
31
|
+
The default build is optimized for browsers, to load the node build add `/node`:
|
32
|
+
|
33
|
+
```js
|
34
|
+
import { fireproof } from '@fireproof/core/node'
|
35
|
+
```
|
36
|
+
|
37
|
+
Add the database to any web page via HTML script tag:
|
28
38
|
|
29
39
|
```html
|
30
40
|
<script src="https://cdn.jsdelivr.net/npm/@fireproof/core/dist/web/fireproof.iife.js"></script>
|
31
41
|
```
|
32
42
|
|
33
|
-
|
43
|
+
Go ahead and write features, then [connect to any cloud backend](https://www.npmjs.com/package/@fireproof/connect) later.
|
34
44
|
|
35
45
|
### JavaScript Example
|
36
46
|
|
@@ -50,7 +60,6 @@ const result = await db.query("age", { range: [40, 52] })
|
|
50
60
|
|
51
61
|
Jump to the docs site [for JavaScript API basics.](https://use-fireproof.com/docs/database-api/basics) You can [find a real-world JavaScript app here.](https://github.com/mlc-ai/web-stable-diffusion/pull/52) Fireproof has been tested in many JavaScript environments. Read more about [bundler support](https://use-fireproof.com/docs/bundling).
|
52
62
|
|
53
|
-
|
54
63
|
### React Example
|
55
64
|
|
56
65
|
Fireproof has React hooks so you can avoid boilerplate and write expressive code. Instead of dealing with React contexts and reducers, simple hooks make your JSON documents feel like `setState()` objects.
|
@@ -67,7 +76,7 @@ Read the [step-by-step React tutorial](https://use-fireproof.com/docs/react-tuto
|
|
67
76
|
|
68
77
|
## Why choose Fireproof
|
69
78
|
|
70
|
-
Fireproof has a unique take on distributed data integrity, rooted in immutable data and cryptographically verifiable protocols. This allows you to add live data to
|
79
|
+
Fireproof has a unique take on distributed data integrity, rooted in immutable data and cryptographically verifiable protocols. This allows you to add live data to any app without complex configuration or installation (it's just an npm module) and if you decide to connect to the cloud you can easily choose storage providers or connect to your own S3 bucket. End-to-end encryption allows you to manage keys separately from data, defining custom security policies, so you can get started writing app features today, and connect to any environment when you are ready. This infrastructure independence makes Fireproof great for brownfield and greenfield projects alike.
|
71
80
|
|
72
81
|
[Read more about the thinking behind Fireproof on our blog.](https://fireproof.storage/blog/) The community is active on [Discord](https://discord.gg/cCryrNHePH) and [X](https://twitter.com/FireproofStorge), among other places.
|
73
82
|
|
@@ -91,8 +91,9 @@ var import_block = require("multiformats/block");
|
|
91
91
|
var import_link = require("multiformats/link");
|
92
92
|
var import_sha2 = require("multiformats/hashes/sha2");
|
93
93
|
var codec = __toESM(require("@ipld/dag-cbor"), 1);
|
94
|
-
var import_crdt = require("@
|
95
|
-
var import_clock = require("@
|
94
|
+
var import_crdt = require("@web3-storage/pail/crdt");
|
95
|
+
var import_clock = require("@web3-storage/pail/clock");
|
96
|
+
var Batch = __toESM(require("@web3-storage/pail/crdt/batch"), 1);
|
96
97
|
var import_encrypted_blockstore = require("@fireproof/encrypted-blockstore");
|
97
98
|
|
98
99
|
// src/files.ts
|
@@ -168,30 +169,39 @@ function time(tag) {
|
|
168
169
|
}
|
169
170
|
function timeEnd(tag) {
|
170
171
|
}
|
171
|
-
async function applyBulkUpdateToCrdt(tblocks, head, updates
|
172
|
-
let result;
|
173
|
-
|
174
|
-
const
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
if (!isReturned) {
|
179
|
-
const hasRoot = await tblocks.get(result.root);
|
180
|
-
if (!hasRoot) {
|
181
|
-
throw new Error(
|
182
|
-
`missing root in additions: ${result.additions.length} ${resRoot} keys: ${updates.map((u) => u.key).toString()}`
|
183
|
-
);
|
184
|
-
result.head = head;
|
185
|
-
}
|
172
|
+
async function applyBulkUpdateToCrdt(tblocks, head, updates) {
|
173
|
+
let result = null;
|
174
|
+
if (updates.length > 1) {
|
175
|
+
const batch = await Batch.create(tblocks, head);
|
176
|
+
for (const update of updates) {
|
177
|
+
const link = await writeDocContent(tblocks, update);
|
178
|
+
await batch.put(update.key, link);
|
186
179
|
}
|
187
|
-
|
188
|
-
|
189
|
-
|
180
|
+
result = await batch.commit();
|
181
|
+
} else {
|
182
|
+
for (const update of updates) {
|
183
|
+
const link = await writeDocContent(tblocks, update);
|
184
|
+
result = await (0, import_crdt.put)(tblocks, head, update.key, link);
|
185
|
+
const resRoot = result.root.toString();
|
186
|
+
const isReturned = result.additions.some((a) => a.cid.toString() === resRoot);
|
187
|
+
if (!isReturned) {
|
188
|
+
const hasRoot = await tblocks.get(result.root);
|
189
|
+
if (!hasRoot) {
|
190
|
+
throw new Error(
|
191
|
+
`missing root in additions: ${result.additions.length} ${resRoot} keys: ${updates.map((u) => u.key).toString()}`
|
192
|
+
);
|
193
|
+
}
|
190
194
|
}
|
191
|
-
head = result.head;
|
192
195
|
}
|
193
196
|
}
|
194
|
-
|
197
|
+
if (!result)
|
198
|
+
throw new Error("Missing result");
|
199
|
+
if (result.event) {
|
200
|
+
for (const { cid, bytes } of [...result.additions, ...result.removals, result.event]) {
|
201
|
+
tblocks.putSync(cid, bytes);
|
202
|
+
}
|
203
|
+
}
|
204
|
+
return { head: result.head };
|
195
205
|
}
|
196
206
|
async function writeDocContent(blocks, update) {
|
197
207
|
let value;
|
@@ -329,38 +339,34 @@ async function gatherUpdates(blocks, eventsFetcher, head, since, updates = [], k
|
|
329
339
|
const { value: event } = await eventsFetcher.get(link);
|
330
340
|
if (!event)
|
331
341
|
continue;
|
332
|
-
const {
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
} else {
|
347
|
-
keys.add(key);
|
348
|
-
const docValue = await getValueFromLink(blocks, value);
|
349
|
-
updates.push({ key, value: docValue.doc, del: docValue.del, clock: link });
|
350
|
-
limit--;
|
351
|
-
if (event.parents) {
|
352
|
-
updates = await gatherUpdates(
|
353
|
-
blocks,
|
354
|
-
eventsFetcher,
|
355
|
-
event.parents,
|
356
|
-
since,
|
357
|
-
updates,
|
358
|
-
keys,
|
359
|
-
didLinks,
|
360
|
-
limit
|
361
|
-
);
|
342
|
+
const { type } = event.data;
|
343
|
+
let ops = [];
|
344
|
+
if (type === "batch") {
|
345
|
+
ops = event.data.ops;
|
346
|
+
} else if (type === "put") {
|
347
|
+
ops = [event.data];
|
348
|
+
}
|
349
|
+
for (let i = ops.length - 1; i >= 0; i--) {
|
350
|
+
const { key, value } = ops[i];
|
351
|
+
if (!keys.has(key)) {
|
352
|
+
const docValue = await getValueFromLink(blocks, value);
|
353
|
+
updates.push({ key, value: docValue.doc, del: docValue.del, clock: link });
|
354
|
+
limit--;
|
355
|
+
keys.add(key);
|
362
356
|
}
|
363
357
|
}
|
358
|
+
if (event.parents) {
|
359
|
+
updates = await gatherUpdates(
|
360
|
+
blocks,
|
361
|
+
eventsFetcher,
|
362
|
+
event.parents,
|
363
|
+
since,
|
364
|
+
updates,
|
365
|
+
keys,
|
366
|
+
didLinks,
|
367
|
+
limit
|
368
|
+
);
|
369
|
+
}
|
364
370
|
}
|
365
371
|
return updates;
|
366
372
|
}
|
@@ -771,8 +777,8 @@ function makeMapFnFromName(name) {
|
|
771
777
|
}
|
772
778
|
|
773
779
|
// src/crdt-clock.ts
|
774
|
-
var import_clock2 = require("@
|
775
|
-
var import_crdt2 = require("@
|
780
|
+
var import_clock2 = require("@web3-storage/pail/clock");
|
781
|
+
var import_crdt2 = require("@web3-storage/pail/crdt");
|
776
782
|
|
777
783
|
// src/apply-head-queue.ts
|
778
784
|
function applyHeadQueue(worker) {
|
@@ -969,12 +975,12 @@ var CRDT = class {
|
|
969
975
|
}
|
970
976
|
});
|
971
977
|
}
|
972
|
-
async bulk(updates
|
978
|
+
async bulk(updates) {
|
973
979
|
await this.ready;
|
974
980
|
const prevHead = [...this.clock.head];
|
975
981
|
const meta = await this.blockstore.transaction(
|
976
982
|
async (blocks) => {
|
977
|
-
const { head } = await applyBulkUpdateToCrdt(blocks, this.clock.head, updates
|
983
|
+
const { head } = await applyBulkUpdateToCrdt(blocks, this.clock.head, updates);
|
978
984
|
updates = updates.map(({ key, value, del, clock }) => {
|
979
985
|
readFiles(this.blockstore, { doc: value });
|
980
986
|
return { key, value, del, clock };
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/fireproof.ts","../../src/database.ts","../../src/write-queue.ts","../../src/crdt.ts","../../src/eb-web.ts","../../src/crdt-helpers.ts","../../src/files.ts","../../src/indexer-helpers.ts","../../src/index.ts","../../src/crdt-clock.ts","../../src/apply-head-queue.ts"],"sourcesContent":["export * from './database'\nexport * from \"./types\"\n","import { uuidv7 } from 'uuidv7'\n\nimport { WriteQueue, writeQueue } from './write-queue'\nimport { CRDT } from './crdt'\nimport { index } from './index'\nimport type {\n CRDTMeta,\n DocUpdate,\n ClockHead,\n Doc,\n ConfigOpts,\n MapFn,\n QueryOpts,\n ChangesOptions,\n DocRecord\n} from './types'\nimport { DbResponse, ChangesResponse } from './types'\nimport { EncryptedBlockstore } from '@fireproof/encrypted-blockstore'\n\ntype DbName = string | null\n\nexport class Database {\n static databases: Map<string, Database> = new Map()\n\n name: DbName\n opts: ConfigOpts = {}\n\n _listening = false\n _listeners: Set<ListenerFn> = new Set()\n _noupdate_listeners: Set<ListenerFn> = new Set()\n _crdt: CRDT\n _writeQueue: WriteQueue\n\n blockstore: EncryptedBlockstore\n\n constructor(name?: string, opts?: ConfigOpts) {\n this.name = name || null\n this.opts = opts || this.opts\n this._crdt = new CRDT(name, this.opts)\n this.blockstore = this._crdt.blockstore // for connector compatibility\n this._writeQueue = writeQueue(async (updates: DocUpdate[]) => {\n return await this._crdt.bulk(updates)\n }) //, Infinity)\n this._crdt.clock.onTock(() => {\n this._no_update_notify()\n })\n }\n\n async get<T extends DocRecord = {}>(id: string): Promise<Doc<T>> {\n const got = await this._crdt.get(id).catch(e => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n e.message = `Not found: ${id} - ` + e.message\n throw e\n })\n if (!got) throw new Error(`Not found: ${id}`)\n const { doc } = got\n return { _id: id, ...doc } as Doc<T>\n }\n\n async put<T extends DocRecord = {}>(doc: Doc<T>): Promise<DbResponse> {\n const { _id, ...value } = doc\n const docId = _id || uuidv7()\n const result: CRDTMeta = await this._writeQueue.push({ key: docId, value } as DocUpdate)\n return { id: docId, clock: result?.head } as DbResponse\n }\n\n async del(id: string): Promise<DbResponse> {\n const result = await this._writeQueue.push({ key: id, del: true })\n return { id, clock: result?.head } as DbResponse\n }\n\n async changes<T extends DocRecord = {}>(since: ClockHead = [], opts: ChangesOptions = {}): Promise<ChangesResponse<T>> {\n const { result, head } = await this._crdt.changes(since, opts)\n const rows = result.map(({ key, value, del, clock }) => ({\n key,\n value: (del ? { _id: key, _deleted: true } : { _id: key, ...value }) as Doc<T>,\n clock\n }))\n return { rows, clock: head }\n }\n\n async allDocs<T extends DocRecord = {}>() {\n const { result, head } = await this._crdt.allDocs()\n const rows = result.map(({ key, value, del }) => ({\n key,\n value: (del ? { _id: key, _deleted: true } : { _id: key, ...value }) as Doc<T>\n }))\n return { rows, clock: head }\n }\n\n async allDocuments<T extends DocRecord = {}>() {\n return this.allDocs<T>()\n }\n\n subscribe(listener: ListenerFn | NoUpdateListenerFn, updates?: boolean): () => void {\n if (updates) {\n if (!this._listening) {\n this._listening = true\n this._crdt.clock.onTick((updates: DocUpdate[]) => {\n void this._notify(updates)\n })\n }\n this._listeners.add(listener)\n return () => {\n this._listeners.delete(listener)\n }\n } else {\n this._noupdate_listeners.add(listener)\n return () => {\n this._noupdate_listeners.delete(listener)\n }\n }\n }\n\n // todo if we add this onto dbs in fireproof.ts then we can make index.ts a separate package\n async query<T extends DocRecord = {}>(field: string | MapFn, opts: QueryOpts = {}) {\n const idx =\n typeof field === 'string'\n ? index({ _crdt: this._crdt }, field)\n : index({ _crdt: this._crdt }, makeName(field.toString()), field)\n return await idx.query<T>(opts)\n }\n\n async compact() {\n await this._crdt.compact()\n }\n\n async _notify(updates: DocUpdate[]) {\n if (this._listeners.size) {\n const docs: Doc[] = updates.map(({ key, value }) => ({ _id: key, ...value }))\n for (const listener of this._listeners) {\n await (async () => await listener(docs))().catch((e: Error) => {\n console.error('subscriber error', e)\n })\n }\n }\n }\n\n async _no_update_notify() {\n if (this._noupdate_listeners.size) {\n for (const listener of this._noupdate_listeners) {\n await (async () => await listener([]))().catch((e: Error) => {\n console.error('subscriber error', e)\n })\n }\n }\n }\n}\n\ntype UpdateListenerFn = <T extends DocRecord = {}>(docs: Doc<T>[]) => Promise<void> | void\ntype NoUpdateListenerFn = () => Promise<void> | void\ntype ListenerFn = UpdateListenerFn | NoUpdateListenerFn\n\nexport function fireproof(name: string, opts?: ConfigOpts): Database {\n if (!Database.databases.has(name)) {\n Database.databases.set(name, new Database(name, opts))\n }\n return Database.databases.get(name)!\n}\n\nfunction makeName(fnString: string) {\n const regex = /\\(([^,()]+,\\s*[^,()]+|\\[[^\\]]+\\],\\s*[^,()]+)\\)/g\n let found: RegExpExecArray | null = null\n const matches = Array.from(fnString.matchAll(regex), match => match[1].trim())\n if (matches.length === 0) {\n found = /=>\\s*(.*)/.exec(fnString)\n }\n if (!found) {\n return fnString\n } else {\n // it's a consise arrow function, match everything after the arrow\n return found[1]\n }\n}\n","import { CRDTMeta, DocUpdate } from './types'\n\ntype WorkerFunction = (tasks: DocUpdate[]) => Promise<CRDTMeta>;\n\nexport type WriteQueue = {\n push(task: DocUpdate): Promise<CRDTMeta>;\n};\n\nexport function writeQueue(worker: WorkerFunction, payload: number = Infinity, unbounded: boolean = false): WriteQueue {\n const queue: {\n task: DocUpdate;\n resolve: (result: CRDTMeta) => void;\n reject: (error: Error) => void;\n }[] = []\n let isProcessing = false\n\n async function process() {\n if (isProcessing || queue.length === 0) return\n isProcessing = true\n\n const tasksToProcess = queue.splice(0, payload)\n const updates = tasksToProcess.map(item => item.task)\n\n if (unbounded) {\n // Run all updates in parallel and resolve/reject them individually\n const promises = updates.map(async (update, index) => {\n try {\n const result = await worker([update])\n tasksToProcess[index].resolve(result)\n } catch (error) {\n tasksToProcess[index].reject(error as Error)\n }\n })\n\n await Promise.all(promises)\n } else {\n // Original logic: Run updates in a batch and resolve/reject them together\n try {\n const result = await worker(updates)\n tasksToProcess.forEach(task => task.resolve(result))\n } catch (error) {\n tasksToProcess.forEach(task => task.reject(error as Error))\n }\n }\n\n isProcessing = false\n void process()\n }\n\n return {\n push(task: DocUpdate): Promise<CRDTMeta> {\n return new Promise<CRDTMeta>((resolve, reject) => {\n queue.push({ task, resolve, reject })\n void process()\n })\n }\n }\n}\n","import {\n EncryptedBlockstore,\n type CompactionFetcher,\n type TransactionMeta,\n type CarTransaction\n} from '@fireproof/encrypted-blockstore'\n\nimport { store, crypto } from './eb-web'\n\nimport {\n clockChangesSince,\n applyBulkUpdateToCrdt,\n getValueFromCrdt,\n readFiles,\n getAllEntries,\n clockVis,\n getBlock,\n doCompact\n} from './crdt-helpers'\nimport type {\n DocUpdate,\n CRDTMeta,\n ClockHead,\n ConfigOpts,\n ChangesOptions,\n IdxMetaMap\n} from './types'\nimport { index, type Index } from './index'\nimport { CRDTClock } from './crdt-clock'\n\nexport class CRDT {\n name: string | null\n opts: ConfigOpts = {}\n ready: Promise<void>\n blockstore: EncryptedBlockstore\n indexBlockstore: EncryptedBlockstore\n\n indexers: Map<string, Index> = new Map()\n\n clock: CRDTClock = new CRDTClock()\n\n constructor(name?: string, opts?: ConfigOpts) {\n this.name = name || null\n this.opts = opts || this.opts\n this.blockstore = new EncryptedBlockstore({\n name,\n applyMeta: async (meta: TransactionMeta) => {\n const crdtMeta = meta as unknown as CRDTMeta\n await this.clock.applyHead(crdtMeta.head, [])\n },\n compact: async (blocks: CompactionFetcher) => {\n await doCompact(blocks, this.clock.head)\n return { head: this.clock.head } as TransactionMeta\n },\n autoCompact: this.opts.autoCompact || 100,\n crypto,\n store,\n public: this.opts.public,\n meta: this.opts.meta\n })\n this.clock.blockstore = this.blockstore\n this.indexBlockstore = new EncryptedBlockstore({\n name: this.opts.persistIndexes && this.name ? this.name + '.idx' : undefined,\n applyMeta: async (meta: TransactionMeta) => {\n const idxCarMeta = meta as unknown as IdxMetaMap\n for (const [name, idx] of Object.entries(idxCarMeta.indexes)) {\n index({ _crdt: this }, name, undefined, idx as any)\n }\n },\n crypto,\n public: this.opts.public,\n store\n })\n this.ready = Promise.all([this.blockstore.ready, this.indexBlockstore.ready]).then(() => {})\n this.clock.onZoom(() => {\n for (const idx of this.indexers.values()) {\n idx._resetIndex()\n }\n })\n }\n\n async bulk(updates: DocUpdate[], options?: object): Promise<CRDTMeta> {\n await this.ready\n const prevHead = [...this.clock.head]\n const meta = (await this.blockstore.transaction(\n async (blocks: CarTransaction): Promise<TransactionMeta> => {\n const { head } = await applyBulkUpdateToCrdt(blocks, this.clock.head, updates, options)\n updates = updates.map(({ key, value, del, clock }) => {\n readFiles(this.blockstore, { doc: value })\n return { key, value, del, clock }\n })\n return { head } as TransactionMeta\n }\n )) as CRDTMeta\n await this.clock.applyHead(meta.head, prevHead, updates)\n return meta\n }\n\n // if (snap) await this.clock.applyHead(crdtMeta.head, this.clock.head)\n\n async allDocs() {\n await this.ready\n const result: DocUpdate[] = []\n for await (const entry of getAllEntries(this.blockstore, this.clock.head)) {\n result.push(entry)\n }\n return { result, head: this.clock.head }\n }\n\n async vis() {\n await this.ready\n const txt: string[] = []\n for await (const line of clockVis(this.blockstore, this.clock.head)) {\n txt.push(line)\n }\n return txt.join('\\n')\n }\n\n async getBlock(cidString: string) {\n await this.ready\n return await getBlock(this.blockstore, cidString)\n }\n\n async get(key: string) {\n await this.ready\n const result = await getValueFromCrdt(this.blockstore, this.clock.head, key)\n if (result.del) return null\n return result\n }\n\n async changes(since: ClockHead = [], opts: ChangesOptions = {}) {\n await this.ready\n return await clockChangesSince(this.blockstore, this.clock.head, since, opts)\n }\n\n async compact() {\n return await this.blockstore.compact()\n }\n}\n","import * as crypto from '@fireproof/encrypted-blockstore/crypto-web'\nimport * as store from '@fireproof/encrypted-blockstore/store-web'\n\nexport { store, crypto }\n","import { encode, decode, Block } from 'multiformats/block'\nimport { parse } from 'multiformats/link'\nimport { sha256 as hasher } from 'multiformats/hashes/sha2'\nimport * as codec from '@ipld/dag-cbor'\nimport { put, get, entries, EventData, root } from '@alanshaw/pail/crdt'\nimport { EventFetcher, vis } from '@alanshaw/pail/clock'\nimport {\n type EncryptedBlockstore,\n type CompactionFetcher,\n CarTransaction,\n TransactionMeta,\n BlockFetcher\n} from '@fireproof/encrypted-blockstore'\nimport type {\n DocUpdate,\n ClockHead,\n AnyLink,\n DocValue,\n CRDTMeta,\n ChangesOptions,\n Doc,\n DocFileMeta,\n DocFiles\n} from './types'\nimport { decodeFile, encodeFile } from './files'\n\nfunction time(tag:string) {\n // console.time(tag)\n}\n\nfunction timeEnd(tag:string) {\n // console.timeEnd(tag)\n}\n\n\nexport async function applyBulkUpdateToCrdt(\n tblocks: CarTransaction,\n head: ClockHead,\n updates: DocUpdate[],\n options?: object\n): Promise<CRDTMeta> {\n let result\n for (const update of updates) {\n const link = await writeDocContent(tblocks, update)\n // console.time('crdt put')\n result = await put(tblocks, head, update.key, link, options)\n // console.timeEnd('crdt put')\n const resRoot = result.root.toString()\n const isReturned = result.additions.some(a => a.cid.toString() === resRoot)\n if (!isReturned) {\n const hasRoot = await tblocks.get(result.root) // is a db-wide get\n if (!hasRoot) {\n throw new Error(\n `missing root in additions: ${result.additions.length} ${resRoot} keys: ${updates\n .map(u => u.key)\n .toString()}`\n )\n\n // make sure https://github.com/alanshaw/pail/pull/20 is applied\n result.head = head\n }\n }\n if (result.event) { // ...result.removals can be used to mark slabs for compaction\n for (const { cid, bytes } of [...result.additions, result.event]) {\n tblocks.putSync(cid, bytes)\n }\n head = result.head\n }\n }\n return { head }\n}\n\n// this whole thing can get pulled outside of the write queue\nasync function writeDocContent(blocks: CarTransaction, update: DocUpdate): Promise<AnyLink> {\n let value: DocValue\n if (update.del) {\n value = { del: true }\n } else {\n await processFiles(blocks, update.value as Doc)\n value = { doc: update.value }\n }\n const block = await encode({ value, hasher, codec })\n blocks.putSync(block.cid, block.bytes)\n return block.cid\n}\n\nasync function processFiles(blocks: CarTransaction, doc: Doc) {\n if (doc._files) {\n await processFileset(blocks, doc._files)\n }\n if (doc._publicFiles) {\n await processFileset(blocks, doc._publicFiles, true)\n }\n}\n\nasync function processFileset(blocks: CarTransaction, files: DocFiles, publicFiles = false) {\n const dbBlockstore = blocks.parent\n const t = new CarTransaction(dbBlockstore) // maybe this should move to encrypted-blockstore\n const didPut = []\n // let totalSize = 0\n for (const filename in files) {\n if (File === files[filename].constructor) {\n const file = files[filename] as File\n\n // totalSize += file.size\n const { cid, blocks: fileBlocks } = await encodeFile(file)\n didPut.push(filename)\n for (const block of fileBlocks) {\n t.putSync(block.cid, block.bytes)\n }\n files[filename] = { cid, type: file.type, size: file.size } as DocFileMeta\n }\n }\n // todo option to bypass this limit\n // if (totalSize > 1024 * 1024 * 1) throw new Error('Sync limit for files in a single update is 1MB')\n if (didPut.length) {\n const car = await dbBlockstore.loader?.commitFiles(t, { files } as unknown as TransactionMeta, {\n public: publicFiles\n })\n if (car) {\n for (const name of didPut) {\n files[name] = { car, ...files[name] } as DocFileMeta\n }\n }\n }\n}\n\nexport async function getValueFromCrdt(\n blocks: EncryptedBlockstore,\n head: ClockHead,\n key: string\n): Promise<DocValue> {\n if (!head.length) throw new Error('Getting from an empty database')\n const link = await get(blocks, head, key)\n if (!link) throw new Error(`Missing key ${key}`)\n return await getValueFromLink(blocks, link)\n}\n\nexport function readFiles(blocks: EncryptedBlockstore, { doc }: DocValue) {\n if (!doc) return\n if (doc._files) {\n readFileset(blocks, doc._files)\n }\n if (doc._publicFiles) {\n readFileset(blocks, doc._publicFiles, true)\n }\n}\n\nfunction readFileset(blocks: EncryptedBlockstore, files: DocFiles, isPublic = false) {\n for (const filename in files) {\n const fileMeta = files[filename] as DocFileMeta\n if (fileMeta.cid) {\n if (isPublic) {\n fileMeta.url = `https://${fileMeta.cid.toString()}.ipfs.w3s.link/`\n }\n if (fileMeta.car) {\n fileMeta.file = async () =>\n await decodeFile(\n {\n get: async (cid: AnyLink) => {\n return await blocks.getFile(fileMeta.car!, cid, isPublic)\n }\n },\n fileMeta.cid,\n fileMeta\n )\n }\n }\n files[filename] = fileMeta\n }\n}\n\nasync function getValueFromLink(blocks: BlockFetcher, link: AnyLink): Promise<DocValue> {\n const block = await blocks.get(link)\n if (!block) throw new Error(`Missing linked block ${link.toString()}`)\n const { value } = (await decode({ bytes: block.bytes, hasher, codec })) as { value: DocValue }\n readFiles(blocks as EncryptedBlockstore, value)\n return value\n}\n\nclass DirtyEventFetcher<T> extends EventFetcher<T> {\n // @ts-ignore\n async get(link) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n return await super.get(link)\n } catch (e) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n console.error('missing event', link.toString(), e)\n return { value: null }\n }\n }\n}\n\nexport async function clockChangesSince(\n blocks: BlockFetcher,\n head: ClockHead,\n since: ClockHead,\n opts: ChangesOptions\n): Promise<{ result: DocUpdate[]; head: ClockHead }> {\n const eventsFetcher = (\n opts.dirty ? new DirtyEventFetcher<EventData>(blocks) : new EventFetcher<EventData>(blocks)\n ) as EventFetcher<EventData>\n const keys: Set<string> = new Set()\n const updates = await gatherUpdates(\n blocks,\n eventsFetcher,\n head,\n since,\n [],\n keys,\n new Set<string>(),\n opts.limit || Infinity\n )\n return { result: updates.reverse(), head }\n}\n\nasync function gatherUpdates(\n blocks: BlockFetcher,\n eventsFetcher: EventFetcher<EventData>,\n head: ClockHead,\n since: ClockHead,\n updates: DocUpdate[] = [],\n keys: Set<string>,\n didLinks: Set<string>,\n limit: number\n): Promise<DocUpdate[]> {\n if (limit <= 0) return updates\n const sHead = head.map(l => l.toString())\n for (const link of since) {\n if (sHead.includes(link.toString())) {\n return updates\n }\n }\n for (const link of head) {\n if (didLinks.has(link.toString())) continue\n didLinks.add(link.toString())\n const { value: event } = await eventsFetcher.get(link)\n if (!event) continue\n const { key, value } = event.data\n if (keys.has(key)) {\n if (event.parents) {\n updates = await gatherUpdates(\n blocks,\n eventsFetcher,\n event.parents,\n since,\n updates,\n keys,\n didLinks,\n limit\n )\n }\n } else {\n keys.add(key)\n const docValue = await getValueFromLink(blocks, value)\n updates.push({ key, value: docValue.doc, del: docValue.del, clock: link })\n limit--\n if (event.parents) {\n updates = await gatherUpdates(\n blocks,\n eventsFetcher,\n event.parents,\n since,\n updates,\n keys,\n didLinks,\n limit\n )\n }\n }\n }\n return updates\n}\n\nexport async function* getAllEntries(blocks: BlockFetcher, head: ClockHead) {\n // return entries(blocks, head)\n for await (const [key, link] of entries(blocks, head)) {\n const docValue = await getValueFromLink(blocks, link)\n yield { key, value: docValue.doc, del: docValue.del } as DocUpdate\n }\n}\n\nexport async function* clockVis(blocks: EncryptedBlockstore, head: ClockHead) {\n for await (const line of vis(blocks, head)) {\n yield line\n }\n}\n\nlet isCompacting = false\nexport async function doCompact(blockLog: CompactionFetcher, head: ClockHead) {\n if (isCompacting) {\n console.log('already compacting')\n return\n }\n isCompacting = true\n\n time(\"compact head\")\n for (const cid of head) {\n const bl = await blockLog.get(cid)\n if (!bl) throw new Error('Missing head block: ' + cid.toString())\n }\n timeEnd(\"compact head\")\n\n // for await (const blk of blocks.entries()) {\n // const bl = await blockLog.get(blk.cid)\n // if (!bl) throw new Error('Missing tblock: ' + blk.cid.toString())\n // }\n\n // todo maybe remove\n // for await (const blk of blocks.loader!.entries()) {\n // const bl = await blockLog.get(blk.cid)\n // if (!bl) throw new Error('Missing db block: ' + blk.cid.toString())\n // }\n\n time(\"compact all entries\")\n for await (const _entry of getAllEntries(blockLog, head)) {\n // result.push(entry)\n void 1\n }\n timeEnd(\"compact all entries\")\n\n // time(\"compact crdt entries\")\n // for await (const [, link] of entries(blockLog, head)) {\n // const bl = await blockLog.get(link)\n // if (!bl) throw new Error('Missing entry block: ' + link.toString())\n // }\n // timeEnd(\"compact crdt entries\")\n\n time(\"compact clock vis\")\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for await (const _line of vis(blockLog, head)) {\n void 1\n }\n timeEnd(\"compact clock vis\")\n\n time(\"compact root\")\n const result = await root(blockLog, head)\n timeEnd(\"compact root\")\n\n time(\"compact root blocks\")\n for (const { cid, bytes } of [...result.additions, ...result.removals]) {\n blockLog.loggedBlocks.putSync(cid, bytes)\n }\n timeEnd(\"compact root blocks\")\n\n time(\"compact changes\")\n await clockChangesSince(blockLog, head, [], {})\n timeEnd(\"compact changes\")\n\n isCompacting = false\n}\n\nexport async function getBlock(blocks: BlockFetcher, cidString: string) {\n const block = await blocks.get(parse(cidString))\n if (!block) throw new Error(`Missing block ${cidString}`)\n const { cid, value } = await decode({ bytes: block.bytes, codec, hasher })\n return new Block({ cid, value, bytes: block.bytes })\n}\n\n","// from https://github.com/web3-storage/w3up/blob/main/packages/upload-client/src/unixfs.js#L165\nimport * as UnixFS from '@ipld/unixfs'\nimport * as raw from 'multiformats/codecs/raw'\nimport { withMaxChunkSize } from '@ipld/unixfs/file/chunker/fixed'\nimport { withWidth } from '@ipld/unixfs/file/layout/balanced'\n\nimport type { View } from '@ipld/unixfs'\nimport { AnyBlock, AnyLink, DocFileMeta } from './types'\n// import type { Block } from 'multiformats/dist/types/src/block'\n\nimport { exporter, ReadableStorage } from 'ipfs-unixfs-exporter'\n\n// /** @param {import('@ipld/unixfs').View} writer */\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\nconst queuingStrategy = UnixFS.withCapacity()\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\nconst settings = UnixFS.configure({\n fileChunkEncoder: raw,\n smallFileEncoder: raw,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\n chunker: withMaxChunkSize(1024 * 1024),\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\n fileLayout: withWidth(1024)\n})\n\nexport async function encodeFile(blob: BlobLike): Promise<{ cid: AnyLink; blocks: AnyBlock[] }> {\n const readable = createFileEncoderStream(blob)\n const blocks = await collect(readable)\n return { cid: blocks.at(-1).cid, blocks }\n}\n\nexport async function decodeFile(blocks: unknown, cid: AnyLink, meta: DocFileMeta): Promise<File> {\n const entry = await exporter(cid.toString(), blocks as ReadableStorage, { length: meta.size })\n const chunks = []\n for await (const chunk of entry.content()) chunks.push(chunk as Buffer)\n return new File(chunks, entry.name, { type: meta.type, lastModified: 0 })\n}\n\nfunction createFileEncoderStream(blob: BlobLike) {\n /** @type {TransformStream<import('@ipld/unixfs').Block, import('@ipld/unixfs').Block>} */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n const { readable, writable } = new TransformStream({}, queuingStrategy)\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n const unixfsWriter = UnixFS.createWriter({ writable, settings })\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\n const fileBuilder = new UnixFSFileBuilder('', blob)\n void (async () => {\n await fileBuilder.finalize(unixfsWriter)\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n await unixfsWriter.close()\n })()\n return readable\n}\n\nasync function collect<T>(collectable: ReadableStream<T>): Promise<T[]> {\n // /** @type {T[]} */\n const chunks: T[] = []\n await collectable.pipeTo(\n new WritableStream({\n write(chunk) {\n chunks.push(chunk)\n }\n })\n )\n return chunks\n}\n\nclass UnixFSFileBuilder {\n #file\n name: string\n constructor(name: string, file: BlobLike) {\n this.name = name\n this.#file = file\n }\n\n async finalize(writer: View) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n const unixfsFileWriter = UnixFS.createFileWriter(writer)\n await this.#file.stream().pipeTo(\n new WritableStream({\n async write(chunk) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n await unixfsFileWriter.write(chunk as Uint8Array)\n }\n })\n )\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n return await unixfsFileWriter.close()\n }\n}\n\n// ts-unused-exports:disable-next-line\nexport interface BlobLike {\n /**\n * Returns a ReadableStream which yields the Blob data.\n */\n stream: () => ReadableStream\n}\n","import type { Block, Link } from 'multiformats'\nimport { create } from 'multiformats/block'\nimport { sha256 as hasher } from 'multiformats/hashes/sha2'\nimport * as codec from '@ipld/dag-cbor'\n\n// @ts-ignore\nimport charwise from 'charwise'\n// @ts-ignore\nimport * as DbIndex from 'prolly-trees/db-index'\n// @ts-ignore\nimport { bf, simpleCompare } from 'prolly-trees/utils'\n// @ts-ignore\nimport { nocache as cache } from 'prolly-trees/cache'\n// @ts-ignore\nimport { ProllyNode as BaseNode } from 'prolly-trees/base'\n\nimport { AnyLink, DocUpdate, MapFn, DocFragment, IndexKey, IndexUpdate, QueryOpts, IndexRow, AnyBlock, Doc, DocRecord } from './types'\nimport { CarTransaction, BlockFetcher } from '@fireproof/encrypted-blockstore'\nimport { CRDT } from './crdt'\n\nexport class IndexTree {\n cid: AnyLink | null = null\n root: ProllyNode | null = null\n}\n\ntype CompareRef = string | number\ntype CompareKey = [string | number, CompareRef]\n\nconst refCompare = (aRef: CompareRef, bRef: CompareRef) => {\n if (Number.isNaN(aRef)) return -1\n if (Number.isNaN(bRef)) throw new Error('ref may not be Infinity or NaN')\n if (aRef === Infinity) return 1\n // if (!Number.isFinite(bRef)) throw new Error('ref may not be Infinity or NaN')\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n return simpleCompare(aRef, bRef) as number\n}\n\nconst compare = (a: CompareKey, b: CompareKey) => {\n const [aKey, aRef] = a\n const [bKey, bRef] = b\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\n const comp: number = simpleCompare(aKey, bKey)\n if (comp !== 0) return comp\n return refCompare(aRef, bRef)\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\nexport const byKeyOpts: StaticProllyOptions = { cache, chunker: bf(30), codec, hasher, compare }\n// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\nexport const byIdOpts: StaticProllyOptions = { cache, chunker: bf(30), codec, hasher, compare: simpleCompare }\n\nexport function indexEntriesForChanges(\n changes: DocUpdate[],\n mapFn: MapFn\n): { key: [string, string]; value: DocFragment }[] {\n const indexEntries: { key: [string, string]; value: DocFragment }[] = []\n changes.forEach(({ key: _id, value, del }) => {\n if (del || !value) return\n let mapCalled = false\n const mapReturn = mapFn({ _id, ...value }, (k: DocFragment, v?: DocFragment) => {\n mapCalled = true\n if (typeof k === 'undefined') return\n indexEntries.push({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n key: [charwise.encode(k) as string, _id],\n value: v || null\n })\n })\n if (!mapCalled && mapReturn) {\n indexEntries.push({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n key: [charwise.encode(mapReturn) as string, _id],\n value: null\n })\n }\n })\n return indexEntries\n}\n\nfunction makeProllyGetBlock(blocks: BlockFetcher): (address: AnyLink) => Promise<AnyBlock> {\n return async (address: AnyLink) => {\n const block = await blocks.get(address)\n if (!block) throw new Error(`Missing block ${address.toString()}`)\n const { cid, bytes } = block\n return create({ cid, bytes, hasher, codec }) as Promise<AnyBlock>\n }\n}\n\nexport async function bulkIndex(tblocks: CarTransaction, inIndex: IndexTree, indexEntries: IndexUpdate[], opts: StaticProllyOptions): Promise<IndexTree> {\n if (!indexEntries.length) return inIndex\n if (!inIndex.root) {\n if (!inIndex.cid) {\n let returnRootBlock: Block | null = null\n let returnNode: ProllyNode | null = null\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n for await (const node of await DbIndex.create({ get: makeProllyGetBlock(tblocks), list: indexEntries, ...opts }) as ProllyNode[]) {\n const block = await node.block\n await tblocks.put(block.cid, block.bytes)\n returnRootBlock = block\n returnNode = node\n }\n if (!returnNode || !returnRootBlock) throw new Error('failed to create index')\n return { root: returnNode, cid: returnRootBlock.cid }\n } else {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n inIndex.root = await DbIndex.load({ cid: inIndex.cid, get: makeProllyGetBlock(tblocks), ...opts }) as ProllyNode\n }\n }\n const { root, blocks: newBlocks } = await inIndex.root.bulk(indexEntries)\n if (root) {\n for await (const block of newBlocks) {\n await tblocks.put(block.cid, block.bytes)\n }\n return { root, cid: (await root.block).cid }\n } else {\n return { root: null, cid: null }\n }\n}\n\nexport async function loadIndex(tblocks: BlockFetcher, cid: AnyLink, opts: StaticProllyOptions): Promise<ProllyNode> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n return await DbIndex.load({ cid, get: makeProllyGetBlock(tblocks), ...opts }) as ProllyNode\n}\n\nexport async function applyQuery<T extends DocRecord = {}>(crdt: CRDT, resp: { result: IndexRow<T>[] }, query: QueryOpts) {\n if (query.descending) {\n resp.result = resp.result.reverse()\n }\n if (query.limit) {\n resp.result = resp.result.slice(0, query.limit)\n }\n if (query.includeDocs) {\n resp.result = await Promise.all(\n resp.result.map(async row => {\n const val = await crdt.get(row.id)\n const doc = val ? ({ _id: row.id, ...val.doc } as Doc<T>) : null\n return { ...row, doc }\n })\n )\n }\n return {\n rows: resp.result.map(row => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n row.key = (charwise.decode(row.key) as IndexKey)\n if (row.row && !row.value) {\n row.value = row.row\n delete row.row\n }\n return row\n })\n }\n}\n\nexport function encodeRange(range: [DocFragment, DocFragment]): [IndexKey, IndexKey] {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n return range.map(key => charwise.encode(key) as IndexKey) as [IndexKey, IndexKey]\n}\n\nexport function encodeKey(key: DocFragment): string {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n return charwise.encode(key) as string\n}\n\n// ProllyNode type based on the ProllyNode from 'prolly-trees/base'\ninterface ProllyNode extends BaseNode {\n getAllEntries<T extends DocRecord = {}>(): PromiseLike<{ [x: string]: any; result: IndexRow<T>[] }>\n getMany(removeIds: string[]): Promise<{ [x: string]: any; result: IndexKey[] }>\n range<T extends DocRecord = {}>(a: IndexKey, b: IndexKey): Promise<{ result: IndexRow<T>[] }>\n get<T extends DocRecord = {}>(key: string): Promise<{ result: IndexRow<T>[] }>\n bulk(bulk: IndexUpdate[]): PromiseLike<{ root: ProllyNode | null; blocks: Block[] }>\n address: Promise<Link>\n distance: number\n compare: (a: any, b: any) => number\n cache: any\n block: Promise<Block>\n}\n\ninterface StaticProllyOptions {\n cache: any\n chunker: (entry: any, distance: number) => boolean\n codec: any\n hasher: any\n compare: (a: any, b: any) => number\n}\n","import type {\n ClockHead,\n DocUpdate,\n MapFn,\n IndexUpdate,\n QueryOpts,\n IdxMeta,\n DocFragment,\n IdxMetaMap,\n IndexRow,\n Doc,\n DocRecord,\n} from './types'\nimport { EncryptedBlockstore, TransactionMeta } from '@fireproof/encrypted-blockstore'\nimport {\n bulkIndex,\n indexEntriesForChanges,\n byIdOpts,\n byKeyOpts,\n IndexTree,\n applyQuery,\n encodeRange,\n encodeKey,\n loadIndex\n} from './indexer-helpers'\nimport { CRDT } from './crdt'\n\nexport function index(\n { _crdt }: { _crdt: CRDT },\n name: string,\n mapFn?: MapFn,\n meta?: IdxMeta\n): Index {\n if (mapFn && meta) throw new Error('cannot provide both mapFn and meta')\n if (mapFn && mapFn.constructor.name !== 'Function') throw new Error('mapFn must be a function')\n if (_crdt.indexers.has(name)) {\n const idx = _crdt.indexers.get(name)!\n idx.applyMapFn(name, mapFn, meta)\n } else {\n const idx = new Index(_crdt, name, mapFn, meta)\n _crdt.indexers.set(name, idx)\n }\n return _crdt.indexers.get(name)!\n}\n\nexport class Index {\n blockstore: EncryptedBlockstore\n crdt: CRDT\n name: string | null = null\n mapFn: MapFn | null = null\n mapFnString: string = ''\n byKey = new IndexTree()\n byId = new IndexTree()\n indexHead: ClockHead | undefined = undefined\n includeDocsDefault: boolean = false\n initError: Error | null = null\n ready: Promise<void>\n\n constructor(crdt: CRDT, name: string, mapFn?: MapFn, meta?: IdxMeta) {\n this.blockstore = crdt.indexBlockstore\n this.crdt = crdt\n this.applyMapFn(name, mapFn, meta)\n if (!(this.mapFnString || this.initError)) throw new Error('missing mapFnString')\n this.ready = this.blockstore.ready.then(() => {})\n // .then((header: IdxCarHeader) => {\n // // @ts-ignore\n // if (header.head) throw new Error('cannot have head in idx header')\n // if (header.indexes === undefined) throw new Error('missing indexes in idx header')\n // // for (const [name, idx] of Object.entries(header.indexes)) {\n // // index({ _crdt: crdt }, name, undefined, idx as IdxMeta)\n // // }\n // })\n }\n\n applyMapFn<T extends Record<string, any> = {}>(name: string, mapFn?: MapFn, meta?: IdxMeta) {\n if (mapFn && meta) throw new Error('cannot provide both mapFn and meta')\n if (this.name && this.name !== name) throw new Error('cannot change name')\n this.name = name\n try {\n if (meta) {\n // hydrating from header\n if (\n this.indexHead &&\n this.indexHead.map(c => c.toString()).join() !== meta.head.map(c => c.toString()).join()\n ) {\n throw new Error('cannot apply meta to existing index')\n }\n\n if (this.mapFnString) {\n // we already initialized from application code\n if (this.mapFnString !== meta.map) {\n console.log(\n 'cannot apply different mapFn meta: old mapFnString',\n this.mapFnString,\n 'new mapFnString',\n meta.map\n )\n // throw new Error('cannot apply different mapFn meta')\n } else {\n this.byId.cid = meta.byId\n this.byKey.cid = meta.byKey\n this.indexHead = meta.head\n }\n } else {\n // we are first\n this.mapFnString = meta.map\n this.byId.cid = meta.byId\n this.byKey.cid = meta.byKey\n this.indexHead = meta.head\n }\n } else {\n if (this.mapFn) {\n // we already initialized from application code\n if (mapFn) {\n if (this.mapFn.toString() !== mapFn.toString())\n throw new Error('cannot apply different mapFn app2')\n }\n } else {\n // application code is creating an index\n if (!mapFn) {\n mapFn = makeMapFnFromName(name)\n }\n if (this.mapFnString) {\n // we already loaded from a header\n if (this.mapFnString !== mapFn.toString())\n throw new Error('cannot apply different mapFn app')\n } else {\n // we are first\n this.mapFnString = mapFn.toString()\n }\n this.mapFn = mapFn\n }\n }\n const matches = /=>\\s*(.*)/.test(this.mapFnString)\n this.includeDocsDefault = matches\n } catch (e) {\n this.initError = e as Error\n }\n }\n\n async query<T extends DocRecord = {}>(opts: QueryOpts = {}): Promise<{ rows: IndexRow<T>[] }> {\n // this._resetIndex()\n await this._updateIndex()\n await this._hydrateIndex()\n if (!this.byKey.root) return await applyQuery(this.crdt, { result: [] }, opts)\n if (this.includeDocsDefault && opts.includeDocs === undefined) opts.includeDocs = true\n if (opts.range) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n const { result, ...all } = await this.byKey.root.range<T>(...encodeRange(opts.range))\n return await applyQuery(this.crdt, { result, ...all }, opts)\n }\n if (opts.key) {\n const encodedKey = encodeKey(opts.key)\n return await applyQuery(this.crdt, await this.byKey.root.get(encodedKey), opts)\n }\n if (Array.isArray(opts.keys)) {\n const results = await Promise.all(\n opts.keys.map(async (key: DocFragment) => {\n const encodedKey = encodeKey(key)\n return (await applyQuery(this.crdt, await this.byKey.root!.get<T>(encodedKey), opts)).rows\n })\n )\n return { rows: results.flat() }\n }\n if (opts.prefix) {\n if (!Array.isArray(opts.prefix)) opts.prefix = [opts.prefix]\n const start = [...opts.prefix, NaN]\n const end = [...opts.prefix, Infinity]\n const encodedR = encodeRange([start, end])\n return await applyQuery(this.crdt, await this.byKey.root.range(...encodedR), opts)\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\n const { result, ...all } = await this.byKey.root.getAllEntries<T>() // funky return type\n return await applyQuery(\n this.crdt,\n {\n result: result.map(({ key: [k, id], value }) => ({ key: k, id, value })),\n ...all\n },\n opts\n )\n }\n\n _resetIndex() {\n this.byId = new IndexTree()\n this.byKey = new IndexTree()\n this.indexHead = undefined\n }\n\n async _hydrateIndex() {\n if (this.byId.root && this.byKey.root) return\n if (!this.byId.cid || !this.byKey.cid) return\n this.byId.root = await loadIndex(this.blockstore, this.byId.cid, byIdOpts)\n this.byKey.root = await loadIndex(this.blockstore, this.byKey.cid, byKeyOpts)\n }\n\n async _updateIndex() {\n await this.ready\n if (this.initError) throw this.initError\n if (!this.mapFn) throw new Error('No map function defined')\n let result: DocUpdate[], head: ClockHead\n if (!this.indexHead || this.indexHead.length === 0) {\n ;({ result, head } = await this.crdt.allDocs())\n } else {\n ;({ result, head } = await this.crdt.changes(this.indexHead))\n }\n if (result.length === 0) {\n this.indexHead = head\n return { byId: this.byId, byKey: this.byKey }\n }\n let staleKeyIndexEntries: IndexUpdate[] = []\n let removeIdIndexEntries: IndexUpdate[] = []\n if (this.byId.root) {\n const removeIds = result.map(({ key }) => key)\n const { result: oldChangeEntries } = (await this.byId.root.getMany(removeIds)) as {\n result: Array<[string, string] | string>\n }\n staleKeyIndexEntries = oldChangeEntries.map(key => ({ key, del: true }))\n removeIdIndexEntries = oldChangeEntries.map(key => ({ key: key[1], del: true }))\n }\n const indexEntries = indexEntriesForChanges(result, this.mapFn) // use a getter to translate from string\n const byIdIndexEntries: DocUpdate[] = indexEntries.map(({ key }) => ({\n key: key[1],\n value: key\n }))\n const indexerMeta: IdxMetaMap = {indexes: new Map()}\n\n for (const [name, indexer] of this.crdt.indexers) {\n if (indexer.indexHead) {\n indexerMeta.indexes.set(name, {\n byId: indexer.byId.cid,\n byKey: indexer.byKey.cid,\n head: indexer.indexHead,\n map: indexer.mapFnString,\n name: indexer.name\n } as IdxMeta)\n }\n }\n return await this.blockstore.transaction(async (tblocks): Promise<TransactionMeta> => {\n this.byId = await bulkIndex(\n tblocks,\n this.byId,\n removeIdIndexEntries.concat(byIdIndexEntries),\n byIdOpts\n )\n this.byKey = await bulkIndex(\n tblocks,\n this.byKey,\n staleKeyIndexEntries.concat(indexEntries),\n byKeyOpts\n )\n this.indexHead = head\n const idxMeta = {\n byId: this.byId.cid,\n byKey: this.byKey.cid,\n head,\n map: this.mapFnString,\n name: this.name\n } as IdxMeta\n indexerMeta.indexes.set(this.name!, idxMeta) // should this move to after commit?\n return indexerMeta as unknown as TransactionMeta\n })\n }\n}\n\nfunction makeMapFnFromName<T extends DocRecord = {}>(name: keyof Doc<T>): MapFn {\n return doc => doc[name] ?? undefined\n}\n","import { clockChangesSince } from './crdt-helpers'\nimport type { EncryptedBlockstore, CarTransaction } from '@fireproof/encrypted-blockstore'\nimport type { DocUpdate, ClockHead } from './types'\nimport { advance } from '@alanshaw/pail/clock'\nimport { root } from '@alanshaw/pail/crdt'\nimport { applyHeadQueue, ApplyHeadQueue } from './apply-head-queue'\n\nexport class CRDTClock {\n // todo: track local and remote clocks independently, merge on read\n // that way we can drop the whole remote if we need to\n // should go with making sure the local clock only references locally available blockstore on write\n head: ClockHead = []\n\n zoomers: Set<() => void> = new Set()\n watchers: Set<(updates: DocUpdate[]) => void> = new Set()\n emptyWatchers: Set<() => void> = new Set()\n\n blockstore: EncryptedBlockstore | null = null\n\n applyHeadQueue: ApplyHeadQueue\n\n constructor() {\n this.applyHeadQueue = applyHeadQueue(this.int_applyHead.bind(this))\n }\n\n setHead(head: ClockHead) {\n this.head = head\n }\n\n async applyHead(newHead: ClockHead, prevHead: ClockHead, updates: DocUpdate[] | null = null) {\n for await (const { updates: updatesAcc, all } of this.applyHeadQueue.push({\n newHead,\n prevHead,\n updates\n })) {\n this.processUpdates(updatesAcc, all, prevHead)\n }\n }\n\n async processUpdates(updatesAcc: DocUpdate[], all: boolean, prevHead: ClockHead) {\n let internalUpdates = updatesAcc\n if (this.watchers.size && !all) {\n const changes = await clockChangesSince(this.blockstore!, this.head, prevHead, {})\n internalUpdates = changes.result\n }\n this.zoomers.forEach(fn => fn())\n this.notifyWatchers(internalUpdates || [])\n }\n\n notifyWatchers(updates: DocUpdate[]) {\n this.emptyWatchers.forEach(fn => fn())\n this.watchers.forEach(fn => fn(updates || []))\n }\n\n onTick(fn: (updates: DocUpdate[]) => void) {\n this.watchers.add(fn)\n }\n\n onTock(fn: () => void) {\n this.emptyWatchers.add(fn)\n }\n\n onZoom(fn: () => void) {\n this.zoomers.add(fn)\n }\n\n async int_applyHead(newHead: ClockHead, prevHead: ClockHead, localUpdates: boolean) {\n const ogHead = sortClockHead(this.head)\n newHead = sortClockHead(newHead)\n if (compareClockHeads(ogHead, newHead)) {\n return\n }\n const ogPrev = sortClockHead(prevHead)\n if (compareClockHeads(ogHead, ogPrev)) {\n this.setHead(newHead)\n return\n }\n let head = this.head\n const noLoader = !localUpdates\n // const noLoader = this.head.length === 1 && !updates?.length\n if (!this.blockstore) throw new Error('missing blockstore')\n await validateBlocks(newHead, this.blockstore)\n await this.blockstore.transaction(\n async (tblocks: CarTransaction) => {\n head = await advanceBlocks(newHead, tblocks, head)\n const result = await root(tblocks, head)\n for (const { cid, bytes } of [...result.additions, ...result.removals]) {\n tblocks.putSync(cid, bytes)\n }\n return { head }\n },\n { noLoader }\n )\n this.setHead(head)\n }\n}\n\n// Helper functions\nfunction sortClockHead(clockHead: ClockHead) {\n return clockHead.sort((a, b) => a.toString().localeCompare(b.toString()))\n}\n\nasync function validateBlocks(newHead: ClockHead, blockstore: EncryptedBlockstore | null) {\n newHead.map(async cid => {\n const got = await blockstore!.get(cid)\n if (!got) {\n throw new Error('int_applyHead missing block: ' + cid.toString())\n }\n })\n}\n\nfunction compareClockHeads(head1: ClockHead, head2: ClockHead) {\n return head1.toString() === head2.toString()\n}\n\nasync function advanceBlocks(newHead: ClockHead, tblocks: CarTransaction, head: ClockHead) {\n for (const cid of newHead) {\n try {\n head = await advance(tblocks, head, cid)\n } catch (e) {\n console.error('failed to advance', cid.toString(), e)\n continue\n }\n }\n return head\n}\n","import { ClockHead, DocUpdate } from './types'\n\ntype ApplyHeadWorkerFunction = (newHead: ClockHead, prevHead: ClockHead, localUpdates: boolean) => Promise<void>\n\ntype ApplyHeadTask = {\n newHead: ClockHead\n prevHead: ClockHead\n updates: DocUpdate[] | null\n}\n\nexport type ApplyHeadQueue = {\n push(task: ApplyHeadTask): AsyncGenerator<{ updates: DocUpdate[]; all: boolean }, void, unknown>\n}\n\nexport function applyHeadQueue(worker: ApplyHeadWorkerFunction): ApplyHeadQueue {\n const queue: ApplyHeadTask[] = []\n let isProcessing = false\n\n async function* process() {\n if (isProcessing || queue.length === 0) return\n isProcessing = true\n const allUpdates: DocUpdate[] = []\n try {\n while (queue.length > 0) {\n queue.sort((a, b) => (b.updates ? 1 : -1))\n const task = queue.shift()\n if (!task) continue\n\n await worker(task.newHead, task.prevHead, task.updates !== null)\n\n if (task.updates) {\n allUpdates.push(...task.updates)\n }\n // Yield the updates if there are no tasks with updates left in the queue or the current task has updates\n if (!queue.some(t => t.updates) || task.updates) {\n const allTasksHaveUpdates = queue.every(task => task.updates !== null)\n yield { updates: allUpdates, all: allTasksHaveUpdates }\n allUpdates.length = 0\n }\n }\n } finally {\n isProcessing = false\n const generator = process()\n let result = await generator.next()\n while (!result.done) {\n result = await generator.next()\n }\n }\n }\n\n return {\n push(\n task: ApplyHeadTask\n ): AsyncGenerator<{ updates: DocUpdate[]; all: boolean }, void, unknown> {\n queue.push(task)\n return process()\n }\n }\n}\n"],"mappings":"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","names":["index","import_encrypted_blockstore","hasher","import_block","import_sha2","codec","cache","hasher","charwise","root","result","all","import_clock","import_crdt","task","name","updates"]}
|
1
|
+
{"version":3,"sources":["../../src/fireproof.ts","../../src/database.ts","../../src/write-queue.ts","../../src/crdt.ts","../../src/eb-web.ts","../../src/crdt-helpers.ts","../../src/files.ts","../../src/indexer-helpers.ts","../../src/index.ts","../../src/crdt-clock.ts","../../src/apply-head-queue.ts"],"sourcesContent":["export * from './database'\nexport * from \"./types\"\n","import { uuidv7 } from 'uuidv7'\n\nimport { WriteQueue, writeQueue } from './write-queue'\nimport { CRDT } from './crdt'\nimport { index } from './index'\nimport type {\n CRDTMeta,\n DocUpdate,\n ClockHead,\n Doc,\n ConfigOpts,\n MapFn,\n QueryOpts,\n ChangesOptions,\n DocRecord\n} from './types'\nimport { DbResponse, ChangesResponse } from './types'\nimport { EncryptedBlockstore } from '@fireproof/encrypted-blockstore'\n\ntype DbName = string | null\n\nexport class Database {\n static databases: Map<string, Database> = new Map()\n\n name: DbName\n opts: ConfigOpts = {}\n\n _listening = false\n _listeners: Set<ListenerFn> = new Set()\n _noupdate_listeners: Set<ListenerFn> = new Set()\n _crdt: CRDT\n _writeQueue: WriteQueue\n\n blockstore: EncryptedBlockstore\n\n constructor(name?: string, opts?: ConfigOpts) {\n this.name = name || null\n this.opts = opts || this.opts\n this._crdt = new CRDT(name, this.opts)\n this.blockstore = this._crdt.blockstore // for connector compatibility\n this._writeQueue = writeQueue(async (updates: DocUpdate[]) => {\n return await this._crdt.bulk(updates)\n }) //, Infinity)\n this._crdt.clock.onTock(() => {\n this._no_update_notify()\n })\n }\n\n async get<T extends DocRecord = {}>(id: string): Promise<Doc<T>> {\n const got = await this._crdt.get(id).catch(e => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n e.message = `Not found: ${id} - ` + e.message\n throw e\n })\n if (!got) throw new Error(`Not found: ${id}`)\n const { doc } = got\n return { _id: id, ...doc } as Doc<T>\n }\n\n async put<T extends DocRecord = {}>(doc: Doc<T>): Promise<DbResponse> {\n const { _id, ...value } = doc\n const docId = _id || uuidv7()\n const result: CRDTMeta = await this._writeQueue.push({ key: docId, value } as DocUpdate)\n return { id: docId, clock: result?.head } as DbResponse\n }\n\n async del(id: string): Promise<DbResponse> {\n const result = await this._writeQueue.push({ key: id, del: true })\n return { id, clock: result?.head } as DbResponse\n }\n\n async changes<T extends DocRecord = {}>(since: ClockHead = [], opts: ChangesOptions = {}): Promise<ChangesResponse<T>> {\n const { result, head } = await this._crdt.changes(since, opts)\n const rows = result.map(({ key, value, del, clock }) => ({\n key,\n value: (del ? { _id: key, _deleted: true } : { _id: key, ...value }) as Doc<T>,\n clock\n }))\n return { rows, clock: head }\n }\n\n async allDocs<T extends DocRecord = {}>() {\n const { result, head } = await this._crdt.allDocs()\n const rows = result.map(({ key, value, del }) => ({\n key,\n value: (del ? { _id: key, _deleted: true } : { _id: key, ...value }) as Doc<T>\n }))\n return { rows, clock: head }\n }\n\n async allDocuments<T extends DocRecord = {}>() {\n return this.allDocs<T>()\n }\n\n subscribe(listener: ListenerFn | NoUpdateListenerFn, updates?: boolean): () => void {\n if (updates) {\n if (!this._listening) {\n this._listening = true\n this._crdt.clock.onTick((updates: DocUpdate[]) => {\n void this._notify(updates)\n })\n }\n this._listeners.add(listener)\n return () => {\n this._listeners.delete(listener)\n }\n } else {\n this._noupdate_listeners.add(listener)\n return () => {\n this._noupdate_listeners.delete(listener)\n }\n }\n }\n\n // todo if we add this onto dbs in fireproof.ts then we can make index.ts a separate package\n async query<T extends DocRecord = {}>(field: string | MapFn, opts: QueryOpts = {}) {\n const idx =\n typeof field === 'string'\n ? index({ _crdt: this._crdt }, field)\n : index({ _crdt: this._crdt }, makeName(field.toString()), field)\n return await idx.query<T>(opts)\n }\n\n async compact() {\n await this._crdt.compact()\n }\n\n async _notify(updates: DocUpdate[]) {\n if (this._listeners.size) {\n const docs: Doc[] = updates.map(({ key, value }) => ({ _id: key, ...value }))\n for (const listener of this._listeners) {\n await (async () => await listener(docs))().catch((e: Error) => {\n console.error('subscriber error', e)\n })\n }\n }\n }\n\n async _no_update_notify() {\n if (this._noupdate_listeners.size) {\n for (const listener of this._noupdate_listeners) {\n await (async () => await listener([]))().catch((e: Error) => {\n console.error('subscriber error', e)\n })\n }\n }\n }\n}\n\ntype UpdateListenerFn = <T extends DocRecord = {}>(docs: Doc<T>[]) => Promise<void> | void\ntype NoUpdateListenerFn = () => Promise<void> | void\ntype ListenerFn = UpdateListenerFn | NoUpdateListenerFn\n\nexport function fireproof(name: string, opts?: ConfigOpts): Database {\n if (!Database.databases.has(name)) {\n Database.databases.set(name, new Database(name, opts))\n }\n return Database.databases.get(name)!\n}\n\nfunction makeName(fnString: string) {\n const regex = /\\(([^,()]+,\\s*[^,()]+|\\[[^\\]]+\\],\\s*[^,()]+)\\)/g\n let found: RegExpExecArray | null = null\n const matches = Array.from(fnString.matchAll(regex), match => match[1].trim())\n if (matches.length === 0) {\n found = /=>\\s*(.*)/.exec(fnString)\n }\n if (!found) {\n return fnString\n } else {\n // it's a consise arrow function, match everything after the arrow\n return found[1]\n }\n}\n","import { CRDTMeta, DocUpdate } from './types'\n\ntype WorkerFunction = (tasks: DocUpdate[]) => Promise<CRDTMeta>;\n\nexport type WriteQueue = {\n push(task: DocUpdate): Promise<CRDTMeta>;\n};\n\nexport function writeQueue(worker: WorkerFunction, payload: number = Infinity, unbounded: boolean = false): WriteQueue {\n const queue: {\n task: DocUpdate;\n resolve: (result: CRDTMeta) => void;\n reject: (error: Error) => void;\n }[] = []\n let isProcessing = false\n\n async function process() {\n if (isProcessing || queue.length === 0) return\n isProcessing = true\n\n const tasksToProcess = queue.splice(0, payload)\n const updates = tasksToProcess.map(item => item.task)\n\n if (unbounded) {\n // Run all updates in parallel and resolve/reject them individually\n const promises = updates.map(async (update, index) => {\n try {\n const result = await worker([update])\n tasksToProcess[index].resolve(result)\n } catch (error) {\n tasksToProcess[index].reject(error as Error)\n }\n })\n\n await Promise.all(promises)\n } else {\n // Original logic: Run updates in a batch and resolve/reject them together\n try {\n const result = await worker(updates)\n tasksToProcess.forEach(task => task.resolve(result))\n } catch (error) {\n tasksToProcess.forEach(task => task.reject(error as Error))\n }\n }\n\n isProcessing = false\n void process()\n }\n\n return {\n push(task: DocUpdate): Promise<CRDTMeta> {\n return new Promise<CRDTMeta>((resolve, reject) => {\n queue.push({ task, resolve, reject })\n void process()\n })\n }\n }\n}\n","import {\n EncryptedBlockstore,\n type CompactionFetcher,\n type TransactionMeta,\n type CarTransaction\n} from '@fireproof/encrypted-blockstore'\n\nimport { store, crypto } from './eb-web'\n\nimport {\n clockChangesSince,\n applyBulkUpdateToCrdt,\n getValueFromCrdt,\n readFiles,\n getAllEntries,\n clockVis,\n getBlock,\n doCompact\n} from './crdt-helpers'\nimport type {\n DocUpdate,\n CRDTMeta,\n ClockHead,\n ConfigOpts,\n ChangesOptions,\n IdxMetaMap\n} from './types'\nimport { index, type Index } from './index'\nimport { CRDTClock } from './crdt-clock'\n\nexport class CRDT {\n name: string | null\n opts: ConfigOpts = {}\n ready: Promise<void>\n blockstore: EncryptedBlockstore\n indexBlockstore: EncryptedBlockstore\n\n indexers: Map<string, Index> = new Map()\n\n clock: CRDTClock = new CRDTClock()\n\n constructor(name?: string, opts?: ConfigOpts) {\n this.name = name || null\n this.opts = opts || this.opts\n this.blockstore = new EncryptedBlockstore({\n name,\n applyMeta: async (meta: TransactionMeta) => {\n const crdtMeta = meta as unknown as CRDTMeta\n await this.clock.applyHead(crdtMeta.head, [])\n },\n compact: async (blocks: CompactionFetcher) => {\n await doCompact(blocks, this.clock.head)\n return { head: this.clock.head } as TransactionMeta\n },\n autoCompact: this.opts.autoCompact || 100,\n crypto,\n store,\n public: this.opts.public,\n meta: this.opts.meta\n })\n this.clock.blockstore = this.blockstore\n this.indexBlockstore = new EncryptedBlockstore({\n name: this.opts.persistIndexes && this.name ? this.name + '.idx' : undefined,\n applyMeta: async (meta: TransactionMeta) => {\n const idxCarMeta = meta as unknown as IdxMetaMap\n for (const [name, idx] of Object.entries(idxCarMeta.indexes)) {\n index({ _crdt: this }, name, undefined, idx as any)\n }\n },\n crypto,\n public: this.opts.public,\n store\n })\n this.ready = Promise.all([this.blockstore.ready, this.indexBlockstore.ready]).then(() => {})\n this.clock.onZoom(() => {\n for (const idx of this.indexers.values()) {\n idx._resetIndex()\n }\n })\n }\n\n async bulk(updates: DocUpdate[]): Promise<CRDTMeta> {\n await this.ready\n const prevHead = [...this.clock.head]\n const meta = (await this.blockstore.transaction(\n async (blocks: CarTransaction): Promise<TransactionMeta> => {\n const { head } = await applyBulkUpdateToCrdt(blocks, this.clock.head, updates)\n updates = updates.map(({ key, value, del, clock }) => {\n readFiles(this.blockstore, { doc: value })\n return { key, value, del, clock }\n })\n return { head } as TransactionMeta\n }\n )) as CRDTMeta\n await this.clock.applyHead(meta.head, prevHead, updates)\n return meta\n }\n\n // if (snap) await this.clock.applyHead(crdtMeta.head, this.clock.head)\n\n async allDocs() {\n await this.ready\n const result: DocUpdate[] = []\n for await (const entry of getAllEntries(this.blockstore, this.clock.head)) {\n result.push(entry)\n }\n return { result, head: this.clock.head }\n }\n\n async vis() {\n await this.ready\n const txt: string[] = []\n for await (const line of clockVis(this.blockstore, this.clock.head)) {\n txt.push(line)\n }\n return txt.join('\\n')\n }\n\n async getBlock(cidString: string) {\n await this.ready\n return await getBlock(this.blockstore, cidString)\n }\n\n async get(key: string) {\n await this.ready\n const result = await getValueFromCrdt(this.blockstore, this.clock.head, key)\n if (result.del) return null\n return result\n }\n\n async changes(since: ClockHead = [], opts: ChangesOptions = {}) {\n await this.ready\n return await clockChangesSince(this.blockstore, this.clock.head, since, opts)\n }\n\n async compact() {\n return await this.blockstore.compact()\n }\n}\n","import * as crypto from '@fireproof/encrypted-blockstore/crypto-web'\nimport * as store from '@fireproof/encrypted-blockstore/store-web'\n\nexport { store, crypto }\n","import { encode, decode, Block } from 'multiformats/block'\nimport { parse } from 'multiformats/link'\nimport { sha256 as hasher } from 'multiformats/hashes/sha2'\nimport * as codec from '@ipld/dag-cbor'\nimport { put, get, entries, root } from '@web3-storage/pail/crdt'\nimport { Operation, PutOperation } from '@web3-storage/pail/src/crdt/api'\nimport { EventFetcher, vis } from '@web3-storage/pail/clock'\nimport * as Batch from '@web3-storage/pail/crdt/batch'\n\nimport {\n type EncryptedBlockstore,\n type CompactionFetcher,\n CarTransaction,\n TransactionMeta,\n BlockFetcher\n} from '@fireproof/encrypted-blockstore'\nimport type {\n DocUpdate,\n ClockHead,\n AnyLink,\n DocValue,\n CRDTMeta,\n ChangesOptions,\n Doc,\n DocFileMeta,\n DocFiles\n} from './types'\nimport { decodeFile, encodeFile } from './files'\nimport { Result } from '@web3-storage/pail/src/crdt/api'\n\nfunction time(tag: string) {\n // console.time(tag)\n}\n\nfunction timeEnd(tag: string) {\n // console.timeEnd(tag)\n}\n\nexport async function applyBulkUpdateToCrdt(\n tblocks: CarTransaction,\n head: ClockHead,\n updates: DocUpdate[]\n): Promise<CRDTMeta> {\n let result: Result | null = null\n // const batch = await Batch.create(tblocks, init.cid)\n // console.log('applyBulkUpdateToCrdt', updates.length)\n if (updates.length > 1) {\n // throw new Error('batch not implemented')\n const batch = await Batch.create(tblocks, head)\n for (const update of updates) {\n const link = await writeDocContent(tblocks, update)\n await batch.put(update.key, link)\n }\n result = await batch.commit()\n // console.log('batch result', result)\n } else {\n for (const update of updates) {\n const link = await writeDocContent(tblocks, update)\n result = await put(tblocks, head, update.key, link)\n const resRoot = result.root.toString()\n const isReturned = result.additions.some(a => a.cid.toString() === resRoot)\n if (!isReturned) {\n const hasRoot = await tblocks.get(result.root) // is a db-wide get\n if (!hasRoot) {\n throw new Error(\n `missing root in additions: ${result.additions.length} ${resRoot} keys: ${updates\n .map(u => u.key)\n .toString()}`\n )\n }\n }\n }\n }\n if (!result) throw new Error('Missing result')\n\n if (result.event) {\n for (const { cid, bytes } of [...result.additions, ...result.removals, result.event]) {\n tblocks.putSync(cid, bytes)\n }\n }\n return { head: result.head } as CRDTMeta\n}\n\n// this whole thing can get pulled outside of the write queue\nasync function writeDocContent(blocks: CarTransaction, update: DocUpdate): Promise<AnyLink> {\n let value: DocValue\n if (update.del) {\n value = { del: true }\n } else {\n await processFiles(blocks, update.value as Doc)\n value = { doc: update.value }\n }\n const block = await encode({ value, hasher, codec })\n blocks.putSync(block.cid, block.bytes)\n return block.cid\n}\n\nasync function processFiles(blocks: CarTransaction, doc: Doc) {\n if (doc._files) {\n await processFileset(blocks, doc._files)\n }\n if (doc._publicFiles) {\n await processFileset(blocks, doc._publicFiles, true)\n }\n}\n\nasync function processFileset(blocks: CarTransaction, files: DocFiles, publicFiles = false) {\n const dbBlockstore = blocks.parent\n const t = new CarTransaction(dbBlockstore) // maybe this should move to encrypted-blockstore\n const didPut = []\n // let totalSize = 0\n for (const filename in files) {\n if (File === files[filename].constructor) {\n const file = files[filename] as File\n\n // totalSize += file.size\n const { cid, blocks: fileBlocks } = await encodeFile(file)\n didPut.push(filename)\n for (const block of fileBlocks) {\n t.putSync(block.cid, block.bytes)\n }\n files[filename] = { cid, type: file.type, size: file.size } as DocFileMeta\n }\n }\n // todo option to bypass this limit\n // if (totalSize > 1024 * 1024 * 1) throw new Error('Sync limit for files in a single update is 1MB')\n if (didPut.length) {\n const car = await dbBlockstore.loader?.commitFiles(t, { files } as unknown as TransactionMeta, {\n public: publicFiles\n })\n if (car) {\n for (const name of didPut) {\n files[name] = { car, ...files[name] } as DocFileMeta\n }\n }\n }\n}\n\nexport async function getValueFromCrdt(\n blocks: EncryptedBlockstore,\n head: ClockHead,\n key: string\n): Promise<DocValue> {\n if (!head.length) throw new Error('Getting from an empty database')\n const link = await get(blocks, head, key)\n if (!link) throw new Error(`Missing key ${key}`)\n return await getValueFromLink(blocks, link)\n}\n\nexport function readFiles(blocks: EncryptedBlockstore, { doc }: DocValue) {\n if (!doc) return\n if (doc._files) {\n readFileset(blocks, doc._files)\n }\n if (doc._publicFiles) {\n readFileset(blocks, doc._publicFiles, true)\n }\n}\n\nfunction readFileset(blocks: EncryptedBlockstore, files: DocFiles, isPublic = false) {\n for (const filename in files) {\n const fileMeta = files[filename] as DocFileMeta\n if (fileMeta.cid) {\n if (isPublic) {\n fileMeta.url = `https://${fileMeta.cid.toString()}.ipfs.w3s.link/`\n }\n if (fileMeta.car) {\n fileMeta.file = async () =>\n await decodeFile(\n {\n get: async (cid: AnyLink) => {\n return await blocks.getFile(fileMeta.car!, cid, isPublic)\n }\n },\n fileMeta.cid,\n fileMeta\n )\n }\n }\n files[filename] = fileMeta\n }\n}\n\nasync function getValueFromLink(blocks: BlockFetcher, link: AnyLink): Promise<DocValue> {\n const block = await blocks.get(link)\n if (!block) throw new Error(`Missing linked block ${link.toString()}`)\n const { value } = (await decode({ bytes: block.bytes, hasher, codec })) as { value: DocValue }\n readFiles(blocks as EncryptedBlockstore, value)\n return value\n}\n\nclass DirtyEventFetcher<T> extends EventFetcher<T> {\n // @ts-ignore\n async get(link) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n return await super.get(link)\n } catch (e) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n console.error('missing event', link.toString(), e)\n return { value: null }\n }\n }\n}\n\nexport async function clockChangesSince(\n blocks: BlockFetcher,\n head: ClockHead,\n since: ClockHead,\n opts: ChangesOptions\n): Promise<{ result: DocUpdate[]; head: ClockHead }> {\n const eventsFetcher = (\n opts.dirty ? new DirtyEventFetcher<Operation>(blocks) : new EventFetcher<Operation>(blocks)\n ) as EventFetcher<Operation>\n const keys: Set<string> = new Set()\n const updates = await gatherUpdates(\n blocks,\n eventsFetcher,\n head,\n since,\n [],\n keys,\n new Set<string>(),\n opts.limit || Infinity\n )\n return { result: updates.reverse(), head }\n}\n\nasync function gatherUpdates(\n blocks: BlockFetcher,\n eventsFetcher: EventFetcher<Operation>,\n head: ClockHead,\n since: ClockHead,\n updates: DocUpdate[] = [],\n keys: Set<string>,\n didLinks: Set<string>,\n limit: number\n): Promise<DocUpdate[]> {\n if (limit <= 0) return updates\n // if (Math.random() < 0.001) console.log('gatherUpdates', head.length, since.length, updates.length)\n const sHead = head.map(l => l.toString())\n for (const link of since) {\n if (sHead.includes(link.toString())) {\n return updates\n }\n }\n for (const link of head) {\n if (didLinks.has(link.toString())) continue\n didLinks.add(link.toString())\n const { value: event } = await eventsFetcher.get(link)\n if (!event) continue\n const { type } = event.data\n let ops = [] as PutOperation[]\n if (type === 'batch') {\n ops = event.data.ops as PutOperation[]\n } else if (type === 'put') {\n ops = [event.data] as PutOperation[]\n }\n for (let i = ops.length - 1; i >= 0; i--) {\n const { key, value } = ops[i];\n if (!keys.has(key)) {\n // todo option to see all updates\n const docValue = await getValueFromLink(blocks, value)\n updates.push({ key, value: docValue.doc, del: docValue.del, clock: link })\n limit--\n keys.add(key)\n }\n }\n if (event.parents) {\n updates = await gatherUpdates(\n blocks,\n eventsFetcher,\n event.parents,\n since,\n updates,\n keys,\n didLinks,\n limit\n )\n }\n }\n return updates\n}\n\nexport async function* getAllEntries(blocks: BlockFetcher, head: ClockHead) {\n // return entries(blocks, head)\n for await (const [key, link] of entries(blocks, head)) {\n const docValue = await getValueFromLink(blocks, link)\n yield { key, value: docValue.doc, del: docValue.del } as DocUpdate\n }\n}\n\nexport async function* clockVis(blocks: EncryptedBlockstore, head: ClockHead) {\n for await (const line of vis(blocks, head)) {\n yield line\n }\n}\n\nlet isCompacting = false\nexport async function doCompact(blockLog: CompactionFetcher, head: ClockHead) {\n if (isCompacting) {\n console.log('already compacting')\n return\n }\n isCompacting = true\n\n time('compact head')\n for (const cid of head) {\n const bl = await blockLog.get(cid)\n if (!bl) throw new Error('Missing head block: ' + cid.toString())\n }\n timeEnd('compact head')\n\n // for await (const blk of blocks.entries()) {\n // const bl = await blockLog.get(blk.cid)\n // if (!bl) throw new Error('Missing tblock: ' + blk.cid.toString())\n // }\n\n // todo maybe remove\n // for await (const blk of blocks.loader!.entries()) {\n // const bl = await blockLog.get(blk.cid)\n // if (!bl) throw new Error('Missing db block: ' + blk.cid.toString())\n // }\n\n time('compact all entries')\n for await (const _entry of getAllEntries(blockLog, head)) {\n // result.push(entry)\n void 1\n }\n timeEnd('compact all entries')\n\n // time(\"compact crdt entries\")\n // for await (const [, link] of entries(blockLog, head)) {\n // const bl = await blockLog.get(link)\n // if (!bl) throw new Error('Missing entry block: ' + link.toString())\n // }\n // timeEnd(\"compact crdt entries\")\n\n time('compact clock vis')\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for await (const _line of vis(blockLog, head)) {\n void 1\n }\n timeEnd('compact clock vis')\n\n time('compact root')\n const result = await root(blockLog, head)\n timeEnd('compact root')\n\n time('compact root blocks')\n for (const { cid, bytes } of [...result.additions, ...result.removals]) {\n blockLog.loggedBlocks.putSync(cid, bytes)\n }\n timeEnd('compact root blocks')\n\n time('compact changes')\n await clockChangesSince(blockLog, head, [], {})\n timeEnd('compact changes')\n\n isCompacting = false\n}\n\nexport async function getBlock(blocks: BlockFetcher, cidString: string) {\n const block = await blocks.get(parse(cidString))\n if (!block) throw new Error(`Missing block ${cidString}`)\n const { cid, value } = await decode({ bytes: block.bytes, codec, hasher })\n return new Block({ cid, value, bytes: block.bytes })\n}\n","// from https://github.com/web3-storage/w3up/blob/main/packages/upload-client/src/unixfs.js#L165\nimport * as UnixFS from '@ipld/unixfs'\nimport * as raw from 'multiformats/codecs/raw'\nimport { withMaxChunkSize } from '@ipld/unixfs/file/chunker/fixed'\nimport { withWidth } from '@ipld/unixfs/file/layout/balanced'\n\nimport type { View } from '@ipld/unixfs'\nimport { AnyBlock, AnyLink, DocFileMeta } from './types'\n// import type { Block } from 'multiformats/dist/types/src/block'\n\nimport { exporter, ReadableStorage } from 'ipfs-unixfs-exporter'\n\n// /** @param {import('@ipld/unixfs').View} writer */\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\nconst queuingStrategy = UnixFS.withCapacity()\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\nconst settings = UnixFS.configure({\n fileChunkEncoder: raw,\n smallFileEncoder: raw,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\n chunker: withMaxChunkSize(1024 * 1024),\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\n fileLayout: withWidth(1024)\n})\n\nexport async function encodeFile(blob: BlobLike): Promise<{ cid: AnyLink; blocks: AnyBlock[] }> {\n const readable = createFileEncoderStream(blob)\n const blocks = await collect(readable)\n return { cid: blocks.at(-1).cid, blocks }\n}\n\nexport async function decodeFile(blocks: unknown, cid: AnyLink, meta: DocFileMeta): Promise<File> {\n const entry = await exporter(cid.toString(), blocks as ReadableStorage, { length: meta.size })\n const chunks = []\n for await (const chunk of entry.content()) chunks.push(chunk as Buffer)\n return new File(chunks, entry.name, { type: meta.type, lastModified: 0 })\n}\n\nfunction createFileEncoderStream(blob: BlobLike) {\n /** @type {TransformStream<import('@ipld/unixfs').Block, import('@ipld/unixfs').Block>} */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n const { readable, writable } = new TransformStream({}, queuingStrategy)\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n const unixfsWriter = UnixFS.createWriter({ writable, settings })\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\n const fileBuilder = new UnixFSFileBuilder('', blob)\n void (async () => {\n await fileBuilder.finalize(unixfsWriter)\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n await unixfsWriter.close()\n })()\n return readable\n}\n\nasync function collect<T>(collectable: ReadableStream<T>): Promise<T[]> {\n // /** @type {T[]} */\n const chunks: T[] = []\n await collectable.pipeTo(\n new WritableStream({\n write(chunk) {\n chunks.push(chunk)\n }\n })\n )\n return chunks\n}\n\nclass UnixFSFileBuilder {\n #file\n name: string\n constructor(name: string, file: BlobLike) {\n this.name = name\n this.#file = file\n }\n\n async finalize(writer: View) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n const unixfsFileWriter = UnixFS.createFileWriter(writer)\n await this.#file.stream().pipeTo(\n new WritableStream({\n async write(chunk) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n await unixfsFileWriter.write(chunk as Uint8Array)\n }\n })\n )\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n return await unixfsFileWriter.close()\n }\n}\n\n// ts-unused-exports:disable-next-line\nexport interface BlobLike {\n /**\n * Returns a ReadableStream which yields the Blob data.\n */\n stream: () => ReadableStream\n}\n","import type { Block, Link } from 'multiformats'\nimport { create } from 'multiformats/block'\nimport { sha256 as hasher } from 'multiformats/hashes/sha2'\nimport * as codec from '@ipld/dag-cbor'\n\n// @ts-ignore\nimport charwise from 'charwise'\n// @ts-ignore\nimport * as DbIndex from 'prolly-trees/db-index'\n// @ts-ignore\nimport { bf, simpleCompare } from 'prolly-trees/utils'\n// @ts-ignore\nimport { nocache as cache } from 'prolly-trees/cache'\n// @ts-ignore\nimport { ProllyNode as BaseNode } from 'prolly-trees/base'\n\nimport { AnyLink, DocUpdate, MapFn, DocFragment, IndexKey, IndexUpdate, QueryOpts, IndexRow, AnyBlock, Doc, DocRecord } from './types'\nimport { CarTransaction, BlockFetcher } from '@fireproof/encrypted-blockstore'\nimport { CRDT } from './crdt'\n\nexport class IndexTree {\n cid: AnyLink | null = null\n root: ProllyNode | null = null\n}\n\ntype CompareRef = string | number\ntype CompareKey = [string | number, CompareRef]\n\nconst refCompare = (aRef: CompareRef, bRef: CompareRef) => {\n if (Number.isNaN(aRef)) return -1\n if (Number.isNaN(bRef)) throw new Error('ref may not be Infinity or NaN')\n if (aRef === Infinity) return 1\n // if (!Number.isFinite(bRef)) throw new Error('ref may not be Infinity or NaN')\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n return simpleCompare(aRef, bRef) as number\n}\n\nconst compare = (a: CompareKey, b: CompareKey) => {\n const [aKey, aRef] = a\n const [bKey, bRef] = b\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\n const comp: number = simpleCompare(aKey, bKey)\n if (comp !== 0) return comp\n return refCompare(aRef, bRef)\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\nexport const byKeyOpts: StaticProllyOptions = { cache, chunker: bf(30), codec, hasher, compare }\n// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\nexport const byIdOpts: StaticProllyOptions = { cache, chunker: bf(30), codec, hasher, compare: simpleCompare }\n\nexport function indexEntriesForChanges(\n changes: DocUpdate[],\n mapFn: MapFn\n): { key: [string, string]; value: DocFragment }[] {\n const indexEntries: { key: [string, string]; value: DocFragment }[] = []\n changes.forEach(({ key: _id, value, del }) => {\n if (del || !value) return\n let mapCalled = false\n const mapReturn = mapFn({ _id, ...value }, (k: DocFragment, v?: DocFragment) => {\n mapCalled = true\n if (typeof k === 'undefined') return\n indexEntries.push({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n key: [charwise.encode(k) as string, _id],\n value: v || null\n })\n })\n if (!mapCalled && mapReturn) {\n indexEntries.push({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n key: [charwise.encode(mapReturn) as string, _id],\n value: null\n })\n }\n })\n return indexEntries\n}\n\nfunction makeProllyGetBlock(blocks: BlockFetcher): (address: AnyLink) => Promise<AnyBlock> {\n return async (address: AnyLink) => {\n const block = await blocks.get(address)\n if (!block) throw new Error(`Missing block ${address.toString()}`)\n const { cid, bytes } = block\n return create({ cid, bytes, hasher, codec }) as Promise<AnyBlock>\n }\n}\n\nexport async function bulkIndex(tblocks: CarTransaction, inIndex: IndexTree, indexEntries: IndexUpdate[], opts: StaticProllyOptions): Promise<IndexTree> {\n if (!indexEntries.length) return inIndex\n if (!inIndex.root) {\n if (!inIndex.cid) {\n let returnRootBlock: Block | null = null\n let returnNode: ProllyNode | null = null\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n for await (const node of await DbIndex.create({ get: makeProllyGetBlock(tblocks), list: indexEntries, ...opts }) as ProllyNode[]) {\n const block = await node.block\n await tblocks.put(block.cid, block.bytes)\n returnRootBlock = block\n returnNode = node\n }\n if (!returnNode || !returnRootBlock) throw new Error('failed to create index')\n return { root: returnNode, cid: returnRootBlock.cid }\n } else {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n inIndex.root = await DbIndex.load({ cid: inIndex.cid, get: makeProllyGetBlock(tblocks), ...opts }) as ProllyNode\n }\n }\n const { root, blocks: newBlocks } = await inIndex.root.bulk(indexEntries)\n if (root) {\n for await (const block of newBlocks) {\n await tblocks.put(block.cid, block.bytes)\n }\n return { root, cid: (await root.block).cid }\n } else {\n return { root: null, cid: null }\n }\n}\n\nexport async function loadIndex(tblocks: BlockFetcher, cid: AnyLink, opts: StaticProllyOptions): Promise<ProllyNode> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n return await DbIndex.load({ cid, get: makeProllyGetBlock(tblocks), ...opts }) as ProllyNode\n}\n\nexport async function applyQuery<T extends DocRecord = {}>(crdt: CRDT, resp: { result: IndexRow<T>[] }, query: QueryOpts) {\n if (query.descending) {\n resp.result = resp.result.reverse()\n }\n if (query.limit) {\n resp.result = resp.result.slice(0, query.limit)\n }\n if (query.includeDocs) {\n resp.result = await Promise.all(\n resp.result.map(async row => {\n const val = await crdt.get(row.id)\n const doc = val ? ({ _id: row.id, ...val.doc } as Doc<T>) : null\n return { ...row, doc }\n })\n )\n }\n return {\n rows: resp.result.map(row => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n row.key = (charwise.decode(row.key) as IndexKey)\n if (row.row && !row.value) {\n row.value = row.row\n delete row.row\n }\n return row\n })\n }\n}\n\nexport function encodeRange(range: [DocFragment, DocFragment]): [IndexKey, IndexKey] {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n return range.map(key => charwise.encode(key) as IndexKey) as [IndexKey, IndexKey]\n}\n\nexport function encodeKey(key: DocFragment): string {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n return charwise.encode(key) as string\n}\n\n// ProllyNode type based on the ProllyNode from 'prolly-trees/base'\ninterface ProllyNode extends BaseNode {\n getAllEntries<T extends DocRecord = {}>(): PromiseLike<{ [x: string]: any; result: IndexRow<T>[] }>\n getMany(removeIds: string[]): Promise<{ [x: string]: any; result: IndexKey[] }>\n range<T extends DocRecord = {}>(a: IndexKey, b: IndexKey): Promise<{ result: IndexRow<T>[] }>\n get<T extends DocRecord = {}>(key: string): Promise<{ result: IndexRow<T>[] }>\n bulk(bulk: IndexUpdate[]): PromiseLike<{ root: ProllyNode | null; blocks: Block[] }>\n address: Promise<Link>\n distance: number\n compare: (a: any, b: any) => number\n cache: any\n block: Promise<Block>\n}\n\ninterface StaticProllyOptions {\n cache: any\n chunker: (entry: any, distance: number) => boolean\n codec: any\n hasher: any\n compare: (a: any, b: any) => number\n}\n","import type {\n ClockHead,\n DocUpdate,\n MapFn,\n IndexUpdate,\n QueryOpts,\n IdxMeta,\n DocFragment,\n IdxMetaMap,\n IndexRow,\n Doc,\n DocRecord,\n} from './types'\nimport { EncryptedBlockstore, TransactionMeta } from '@fireproof/encrypted-blockstore'\nimport {\n bulkIndex,\n indexEntriesForChanges,\n byIdOpts,\n byKeyOpts,\n IndexTree,\n applyQuery,\n encodeRange,\n encodeKey,\n loadIndex\n} from './indexer-helpers'\nimport { CRDT } from './crdt'\n\nexport function index(\n { _crdt }: { _crdt: CRDT },\n name: string,\n mapFn?: MapFn,\n meta?: IdxMeta\n): Index {\n if (mapFn && meta) throw new Error('cannot provide both mapFn and meta')\n if (mapFn && mapFn.constructor.name !== 'Function') throw new Error('mapFn must be a function')\n if (_crdt.indexers.has(name)) {\n const idx = _crdt.indexers.get(name)!\n idx.applyMapFn(name, mapFn, meta)\n } else {\n const idx = new Index(_crdt, name, mapFn, meta)\n _crdt.indexers.set(name, idx)\n }\n return _crdt.indexers.get(name)!\n}\n\nexport class Index {\n blockstore: EncryptedBlockstore\n crdt: CRDT\n name: string | null = null\n mapFn: MapFn | null = null\n mapFnString: string = ''\n byKey = new IndexTree()\n byId = new IndexTree()\n indexHead: ClockHead | undefined = undefined\n includeDocsDefault: boolean = false\n initError: Error | null = null\n ready: Promise<void>\n\n constructor(crdt: CRDT, name: string, mapFn?: MapFn, meta?: IdxMeta) {\n this.blockstore = crdt.indexBlockstore\n this.crdt = crdt\n this.applyMapFn(name, mapFn, meta)\n if (!(this.mapFnString || this.initError)) throw new Error('missing mapFnString')\n this.ready = this.blockstore.ready.then(() => {})\n // .then((header: IdxCarHeader) => {\n // // @ts-ignore\n // if (header.head) throw new Error('cannot have head in idx header')\n // if (header.indexes === undefined) throw new Error('missing indexes in idx header')\n // // for (const [name, idx] of Object.entries(header.indexes)) {\n // // index({ _crdt: crdt }, name, undefined, idx as IdxMeta)\n // // }\n // })\n }\n\n applyMapFn<T extends Record<string, any> = {}>(name: string, mapFn?: MapFn, meta?: IdxMeta) {\n if (mapFn && meta) throw new Error('cannot provide both mapFn and meta')\n if (this.name && this.name !== name) throw new Error('cannot change name')\n this.name = name\n try {\n if (meta) {\n // hydrating from header\n if (\n this.indexHead &&\n this.indexHead.map(c => c.toString()).join() !== meta.head.map(c => c.toString()).join()\n ) {\n throw new Error('cannot apply meta to existing index')\n }\n\n if (this.mapFnString) {\n // we already initialized from application code\n if (this.mapFnString !== meta.map) {\n console.log(\n 'cannot apply different mapFn meta: old mapFnString',\n this.mapFnString,\n 'new mapFnString',\n meta.map\n )\n // throw new Error('cannot apply different mapFn meta')\n } else {\n this.byId.cid = meta.byId\n this.byKey.cid = meta.byKey\n this.indexHead = meta.head\n }\n } else {\n // we are first\n this.mapFnString = meta.map\n this.byId.cid = meta.byId\n this.byKey.cid = meta.byKey\n this.indexHead = meta.head\n }\n } else {\n if (this.mapFn) {\n // we already initialized from application code\n if (mapFn) {\n if (this.mapFn.toString() !== mapFn.toString())\n throw new Error('cannot apply different mapFn app2')\n }\n } else {\n // application code is creating an index\n if (!mapFn) {\n mapFn = makeMapFnFromName(name)\n }\n if (this.mapFnString) {\n // we already loaded from a header\n if (this.mapFnString !== mapFn.toString())\n throw new Error('cannot apply different mapFn app')\n } else {\n // we are first\n this.mapFnString = mapFn.toString()\n }\n this.mapFn = mapFn\n }\n }\n const matches = /=>\\s*(.*)/.test(this.mapFnString)\n this.includeDocsDefault = matches\n } catch (e) {\n this.initError = e as Error\n }\n }\n\n async query<T extends DocRecord = {}>(opts: QueryOpts = {}): Promise<{ rows: IndexRow<T>[] }> {\n // this._resetIndex()\n await this._updateIndex()\n await this._hydrateIndex()\n if (!this.byKey.root) return await applyQuery(this.crdt, { result: [] }, opts)\n if (this.includeDocsDefault && opts.includeDocs === undefined) opts.includeDocs = true\n if (opts.range) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n const { result, ...all } = await this.byKey.root.range<T>(...encodeRange(opts.range))\n return await applyQuery(this.crdt, { result, ...all }, opts)\n }\n if (opts.key) {\n const encodedKey = encodeKey(opts.key)\n return await applyQuery(this.crdt, await this.byKey.root.get(encodedKey), opts)\n }\n if (Array.isArray(opts.keys)) {\n const results = await Promise.all(\n opts.keys.map(async (key: DocFragment) => {\n const encodedKey = encodeKey(key)\n return (await applyQuery(this.crdt, await this.byKey.root!.get<T>(encodedKey), opts)).rows\n })\n )\n return { rows: results.flat() }\n }\n if (opts.prefix) {\n if (!Array.isArray(opts.prefix)) opts.prefix = [opts.prefix]\n const start = [...opts.prefix, NaN]\n const end = [...opts.prefix, Infinity]\n const encodedR = encodeRange([start, end])\n return await applyQuery(this.crdt, await this.byKey.root.range(...encodedR), opts)\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\n const { result, ...all } = await this.byKey.root.getAllEntries<T>() // funky return type\n return await applyQuery(\n this.crdt,\n {\n result: result.map(({ key: [k, id], value }) => ({ key: k, id, value })),\n ...all\n },\n opts\n )\n }\n\n _resetIndex() {\n this.byId = new IndexTree()\n this.byKey = new IndexTree()\n this.indexHead = undefined\n }\n\n async _hydrateIndex() {\n if (this.byId.root && this.byKey.root) return\n if (!this.byId.cid || !this.byKey.cid) return\n this.byId.root = await loadIndex(this.blockstore, this.byId.cid, byIdOpts)\n this.byKey.root = await loadIndex(this.blockstore, this.byKey.cid, byKeyOpts)\n }\n\n async _updateIndex() {\n await this.ready\n if (this.initError) throw this.initError\n if (!this.mapFn) throw new Error('No map function defined')\n let result: DocUpdate[], head: ClockHead\n if (!this.indexHead || this.indexHead.length === 0) {\n ;({ result, head } = await this.crdt.allDocs())\n } else {\n ;({ result, head } = await this.crdt.changes(this.indexHead))\n }\n if (result.length === 0) {\n this.indexHead = head\n return { byId: this.byId, byKey: this.byKey }\n }\n let staleKeyIndexEntries: IndexUpdate[] = []\n let removeIdIndexEntries: IndexUpdate[] = []\n if (this.byId.root) {\n const removeIds = result.map(({ key }) => key)\n const { result: oldChangeEntries } = (await this.byId.root.getMany(removeIds)) as {\n result: Array<[string, string] | string>\n }\n staleKeyIndexEntries = oldChangeEntries.map(key => ({ key, del: true }))\n removeIdIndexEntries = oldChangeEntries.map(key => ({ key: key[1], del: true }))\n }\n const indexEntries = indexEntriesForChanges(result, this.mapFn) // use a getter to translate from string\n const byIdIndexEntries: DocUpdate[] = indexEntries.map(({ key }) => ({\n key: key[1],\n value: key\n }))\n const indexerMeta: IdxMetaMap = {indexes: new Map()}\n\n for (const [name, indexer] of this.crdt.indexers) {\n if (indexer.indexHead) {\n indexerMeta.indexes.set(name, {\n byId: indexer.byId.cid,\n byKey: indexer.byKey.cid,\n head: indexer.indexHead,\n map: indexer.mapFnString,\n name: indexer.name\n } as IdxMeta)\n }\n }\n return await this.blockstore.transaction(async (tblocks): Promise<TransactionMeta> => {\n this.byId = await bulkIndex(\n tblocks,\n this.byId,\n removeIdIndexEntries.concat(byIdIndexEntries),\n byIdOpts\n )\n this.byKey = await bulkIndex(\n tblocks,\n this.byKey,\n staleKeyIndexEntries.concat(indexEntries),\n byKeyOpts\n )\n this.indexHead = head\n const idxMeta = {\n byId: this.byId.cid,\n byKey: this.byKey.cid,\n head,\n map: this.mapFnString,\n name: this.name\n } as IdxMeta\n indexerMeta.indexes.set(this.name!, idxMeta) // should this move to after commit?\n return indexerMeta as unknown as TransactionMeta\n })\n }\n}\n\nfunction makeMapFnFromName<T extends DocRecord = {}>(name: keyof Doc<T>): MapFn {\n return doc => doc[name] ?? undefined\n}\n","import { clockChangesSince } from './crdt-helpers'\nimport type { EncryptedBlockstore, CarTransaction } from '@fireproof/encrypted-blockstore'\nimport type { DocUpdate, ClockHead } from './types'\nimport { advance } from '@web3-storage/pail/clock'\nimport { root } from '@web3-storage/pail/crdt'\nimport { applyHeadQueue, ApplyHeadQueue } from './apply-head-queue'\n\nexport class CRDTClock {\n // todo: track local and remote clocks independently, merge on read\n // that way we can drop the whole remote if we need to\n // should go with making sure the local clock only references locally available blockstore on write\n head: ClockHead = []\n\n zoomers: Set<() => void> = new Set()\n watchers: Set<(updates: DocUpdate[]) => void> = new Set()\n emptyWatchers: Set<() => void> = new Set()\n\n blockstore: EncryptedBlockstore | null = null\n\n applyHeadQueue: ApplyHeadQueue\n\n constructor() {\n this.applyHeadQueue = applyHeadQueue(this.int_applyHead.bind(this))\n }\n\n setHead(head: ClockHead) {\n this.head = head\n }\n\n async applyHead(newHead: ClockHead, prevHead: ClockHead, updates: DocUpdate[] | null = null) {\n for await (const { updates: updatesAcc, all } of this.applyHeadQueue.push({\n newHead,\n prevHead,\n updates\n })) {\n this.processUpdates(updatesAcc, all, prevHead)\n }\n }\n\n async processUpdates(updatesAcc: DocUpdate[], all: boolean, prevHead: ClockHead) {\n let internalUpdates = updatesAcc\n if (this.watchers.size && !all) {\n const changes = await clockChangesSince(this.blockstore!, this.head, prevHead, {})\n internalUpdates = changes.result\n }\n this.zoomers.forEach(fn => fn())\n this.notifyWatchers(internalUpdates || [])\n }\n\n notifyWatchers(updates: DocUpdate[]) {\n this.emptyWatchers.forEach(fn => fn())\n this.watchers.forEach(fn => fn(updates || []))\n }\n\n onTick(fn: (updates: DocUpdate[]) => void) {\n this.watchers.add(fn)\n }\n\n onTock(fn: () => void) {\n this.emptyWatchers.add(fn)\n }\n\n onZoom(fn: () => void) {\n this.zoomers.add(fn)\n }\n\n async int_applyHead(newHead: ClockHead, prevHead: ClockHead, localUpdates: boolean) {\n const ogHead = sortClockHead(this.head)\n newHead = sortClockHead(newHead)\n if (compareClockHeads(ogHead, newHead)) {\n return\n }\n const ogPrev = sortClockHead(prevHead)\n if (compareClockHeads(ogHead, ogPrev)) {\n this.setHead(newHead)\n return\n }\n let head = this.head\n const noLoader = !localUpdates\n // const noLoader = this.head.length === 1 && !updates?.length\n if (!this.blockstore) throw new Error('missing blockstore')\n await validateBlocks(newHead, this.blockstore)\n await this.blockstore.transaction(\n async (tblocks: CarTransaction) => {\n head = await advanceBlocks(newHead, tblocks, head)\n const result = await root(tblocks, head)\n for (const { cid, bytes } of [...result.additions, ...result.removals]) {\n tblocks.putSync(cid, bytes)\n }\n return { head }\n },\n { noLoader }\n )\n this.setHead(head)\n }\n}\n\n// Helper functions\nfunction sortClockHead(clockHead: ClockHead) {\n return clockHead.sort((a, b) => a.toString().localeCompare(b.toString()))\n}\n\nasync function validateBlocks(newHead: ClockHead, blockstore: EncryptedBlockstore | null) {\n newHead.map(async cid => {\n const got = await blockstore!.get(cid)\n if (!got) {\n throw new Error('int_applyHead missing block: ' + cid.toString())\n }\n })\n}\n\nfunction compareClockHeads(head1: ClockHead, head2: ClockHead) {\n return head1.toString() === head2.toString()\n}\n\nasync function advanceBlocks(newHead: ClockHead, tblocks: CarTransaction, head: ClockHead) {\n for (const cid of newHead) {\n try {\n head = await advance(tblocks, head, cid)\n } catch (e) {\n console.error('failed to advance', cid.toString(), e)\n continue\n }\n }\n return head\n}\n","import { ClockHead, DocUpdate } from './types'\n\ntype ApplyHeadWorkerFunction = (newHead: ClockHead, prevHead: ClockHead, localUpdates: boolean) => Promise<void>\n\ntype ApplyHeadTask = {\n newHead: ClockHead\n prevHead: ClockHead\n updates: DocUpdate[] | null\n}\n\nexport type ApplyHeadQueue = {\n push(task: ApplyHeadTask): AsyncGenerator<{ updates: DocUpdate[]; all: boolean }, void, unknown>\n}\n\nexport function applyHeadQueue(worker: ApplyHeadWorkerFunction): ApplyHeadQueue {\n const queue: ApplyHeadTask[] = []\n let isProcessing = false\n\n async function* process() {\n if (isProcessing || queue.length === 0) return\n isProcessing = true\n const allUpdates: DocUpdate[] = []\n try {\n while (queue.length > 0) {\n queue.sort((a, b) => (b.updates ? 1 : -1))\n const task = queue.shift()\n if (!task) continue\n\n await worker(task.newHead, task.prevHead, task.updates !== null)\n\n if (task.updates) {\n allUpdates.push(...task.updates)\n }\n // Yield the updates if there are no tasks with updates left in the queue or the current task has updates\n if (!queue.some(t => t.updates) || task.updates) {\n const allTasksHaveUpdates = queue.every(task => task.updates !== null)\n yield { updates: allUpdates, all: allTasksHaveUpdates }\n allUpdates.length = 0\n }\n }\n } finally {\n isProcessing = false\n const generator = process()\n let result = await generator.next()\n while (!result.done) {\n result = await generator.next()\n }\n }\n }\n\n return {\n push(\n task: ApplyHeadTask\n ): AsyncGenerator<{ updates: DocUpdate[]; all: boolean }, void, unknown> {\n queue.push(task)\n return process()\n }\n }\n}\n"],"mappings":"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","names":["index","import_encrypted_blockstore","hasher","import_block","import_sha2","codec","cache","hasher","charwise","root","result","all","import_clock","import_crdt","task","name","updates"]}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Link, Block } from 'multiformats';
|
2
|
-
import { EventLink } from '@
|
3
|
-
import {
|
2
|
+
import { EventLink } from '@web3-storage/pail/clock/api';
|
3
|
+
import { Operation } from '@web3-storage/pail/crdt/api';
|
4
4
|
import * as _fireproof_encrypted_blockstore from '@fireproof/encrypted-blockstore';
|
5
5
|
import { DbMeta, EncryptedBlockstore } from '@fireproof/encrypted-blockstore';
|
6
6
|
import * as multiformats_dist_types_src_block from 'multiformats/dist/types/src/block';
|
@@ -12,7 +12,7 @@ type ConfigOpts = {
|
|
12
12
|
persistIndexes?: boolean;
|
13
13
|
autoCompact?: number;
|
14
14
|
};
|
15
|
-
type ClockLink = EventLink<
|
15
|
+
type ClockLink = EventLink<Operation>;
|
16
16
|
type ClockHead = ClockLink[];
|
17
17
|
type DocFragment = Uint8Array | string | number | boolean | null | AnyLink | DocFragment[] | {
|
18
18
|
[key: string]: DocFragment;
|
@@ -236,7 +236,7 @@ declare class CRDT {
|
|
236
236
|
indexers: Map<string, Index>;
|
237
237
|
clock: CRDTClock;
|
238
238
|
constructor(name?: string, opts?: ConfigOpts);
|
239
|
-
bulk(updates: DocUpdate[]
|
239
|
+
bulk(updates: DocUpdate[]): Promise<CRDTMeta>;
|
240
240
|
allDocs(): Promise<{
|
241
241
|
result: DocUpdate[];
|
242
242
|
head: ClockHead;
|