@fireproof/core 0.8.0 → 0.10.1-dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +5 -184
  2. package/dist/fireproof.browser.js +18879 -0
  3. package/dist/fireproof.browser.js.map +7 -0
  4. package/dist/fireproof.cjs.js +9305 -0
  5. package/dist/fireproof.cjs.js.map +7 -0
  6. package/dist/fireproof.esm.js +9295 -0
  7. package/dist/fireproof.esm.js.map +7 -0
  8. package/package.json +57 -105
  9. package/dist/blockstore.js +0 -268
  10. package/dist/clock.js +0 -459
  11. package/dist/crypto.js +0 -63
  12. package/dist/database.js +0 -434
  13. package/dist/db-index.js +0 -403
  14. package/dist/encrypted-block.js +0 -48
  15. package/dist/fireproof.js +0 -84
  16. package/dist/import.js +0 -29
  17. package/dist/listener.js +0 -111
  18. package/dist/loader.js +0 -13
  19. package/dist/prolly.js +0 -405
  20. package/dist/remote.js +0 -102
  21. package/dist/sha1.js +0 -74
  22. package/dist/src/fireproof.d.ts +0 -472
  23. package/dist/src/fireproof.js +0 -81191
  24. package/dist/src/fireproof.js.map +0 -1
  25. package/dist/src/fireproof.mjs +0 -81186
  26. package/dist/src/fireproof.mjs.map +0 -1
  27. package/dist/storage/base.js +0 -426
  28. package/dist/storage/blocksToEncryptedCarBlock.js +0 -144
  29. package/dist/storage/browser.js +0 -62
  30. package/dist/storage/filesystem.js +0 -67
  31. package/dist/storage/rest.js +0 -57
  32. package/dist/storage/ucan.js +0 -0
  33. package/dist/storage/utils.js +0 -144
  34. package/dist/sync.js +0 -218
  35. package/dist/utils.js +0 -16
  36. package/dist/valet.js +0 -102
  37. package/src/blockstore.js +0 -283
  38. package/src/clock.js +0 -486
  39. package/src/crypto.js +0 -70
  40. package/src/database.js +0 -469
  41. package/src/db-index.js +0 -426
  42. package/src/encrypted-block.js +0 -57
  43. package/src/fireproof.js +0 -98
  44. package/src/import.js +0 -34
  45. package/src/link.d.ts +0 -3
  46. package/src/loader.js +0 -16
  47. package/src/prolly.js +0 -445
  48. package/src/remote.js +0 -113
  49. package/src/sha1.js +0 -83
  50. package/src/storage/base.js +0 -463
  51. package/src/storage/browser.js +0 -67
  52. package/src/storage/filesystem.js +0 -73
  53. package/src/storage/rest.js +0 -59
  54. package/src/storage/ucan.js +0 -0
  55. package/src/storage/utils.js +0 -152
  56. package/src/sync.js +0 -237
  57. package/src/valet.js +0 -105
package/package.json CHANGED
@@ -1,99 +1,40 @@
1
1
  {
2
2
  "name": "@fireproof/core",
3
- "version": "0.8.0",
4
- "description": "Live data for React, accelerated by proofs, powered by IPFS",
5
- "main": "dist/src/fireproof.js",
6
- "module": "dist/src/fireproof.mjs",
7
- "typings": "dist/src/fireproof.d.ts",
8
- "types": "dist/src/fireproof.d.ts",
3
+ "version": "0.10.1-dev",
4
+ "description": "Immutable embedded distributed database for the web",
5
+ "main": "dist/fireproof.cjs.js",
6
+ "module": "dist/fireproof.esm.js",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/fireproof.esm.js",
10
+ "require": "./dist/fireproof.cjs.js"
11
+ },
12
+ "./browser": "./dist/fireproof.browser.js"
13
+ },
14
+ "browser": "./dist/fireproof.browser.js",
15
+ "files": [
16
+ "dist/fireproof.*"
17
+ ],
9
18
  "type": "module",
10
19
  "scripts": {
11
- "keygen": "node scripts/keygen.js",
12
- "server": "node scripts/sever.js",
13
- "test": "standard && tsc && npm run test:unencrypted && npm run test:mocha",
14
- "test:unencrypted": "set NO_ENCRYPT=true && npm run test:mocha",
15
- "test:mocha": "mocha test/*.test.js",
16
- "test:watch": "npm run test:mocha -- -w --parallel",
17
- "coverage": "c8 -r html -r text npm test",
18
- "prepublishOnly": "cp ../../README.md . && npm run build",
19
- "postpublish": "rm README.md",
20
- "lint": "standard",
21
- "lint:fix": "standard --fix",
22
- "tsc": "tsc --watch",
23
- "build": "tsc && rollup -c"
20
+ "build": "npm run clean && node ./scripts/build.js",
21
+ "prepublishOnly": "npm run build",
22
+ "clean": "rm -rf dist/*",
23
+ "start": "node ./scripts/serve.js",
24
+ "analyze": "node ./scripts/analyze.js",
25
+ "test:watch": "nodemon -w src -w test -e ts,js --exec \"npm run build && npm run test:node\"",
26
+ "test:node": "node ./scripts/test.js",
27
+ "test:browser": "polendina test/*.js --webpack-config webpack.config.cjs",
28
+ "test": "npm run build && npm run test:node && npm run test:browser",
29
+ "lint": "eslint 'src/**/*.{js,ts}'",
30
+ "lint:fix": "eslint --fix 'src/**/*.{js,ts}'"
24
31
  },
25
32
  "keywords": [
26
- "database",
27
- "JSON",
28
- "document",
29
- "IPLD",
30
- "CID",
31
- "IPFS"
32
- ],
33
- "contributors": [
34
- "J Chris Anderson",
35
- "Alan Shaw",
36
- "Travis Vachon",
37
- "Mikeal Rogers"
33
+ "database"
38
34
  ],
35
+ "author": "J Chris Anderson",
39
36
  "license": "Apache-2.0 OR MIT",
40
- "gptdoc": "Fireproof/API/Usage: import { Fireproof, Index } from '@fireproof/core'; const db = fireproof.storage('app-db-name'); const ok = await db.put({ any: 'json' }); const doc = await db.get(ok.id); await db.del(doc._id); const all = await db.allDocuments(); all.rows.map(({key, value}) => value); useEffect(()=> db.subscribe(updateReactStateFn), []); const index = new Index(db, (doc, map) => map(doc.any, {custom: Object.keys(doc)})); const result = await index.query({range : ['a', 'z']}); result.rows.map(({ key }) => key);",
41
- "dependencies": {
42
- "@ipld/car": "^5.1.0",
43
- "@ipld/dag-cbor": "^9.0.0",
44
- "@jsonlines/core": "^1.0.2",
45
- "@web3-storage/clock": "^0.3.0",
46
- "@web3-storage/w3up-client": "^7.0.0",
47
- "async": "^3.2.4",
48
- "charwise": "^3.0.1",
49
- "cross-fetch": "^3.1.6",
50
- "crypto-browserify": "^3.12.0",
51
- "idb": "^7.1.1",
52
- "ipld-hashmap": "^2.1.18",
53
- "js-crypto-aes": "^1.0.4",
54
- "multiformats": "^11.0.1",
55
- "prolly-trees": "1.0.4",
56
- "randombytes": "^2.1.0",
57
- "simple-peer": "^9.11.1"
58
- },
59
- "devDependencies": {
60
- "@rollup/plugin-alias": "^5.0.0",
61
- "@rollup/plugin-commonjs": "^24.0.1",
62
- "@rollup/plugin-json": "^6.0.0",
63
- "@rollup/plugin-node-resolve": "^15.0.2",
64
- "c8": "^7.12.0",
65
- "esbuild": "^0.17.16",
66
- "fake-indexeddb": "^4.0.1",
67
- "flexsearch": "^0.7.31",
68
- "mocha": "^10.2.0",
69
- "nanoid": "^4.0.0",
70
- "node-polyfill-webpack-plugin": "^2.0.1",
71
- "rollup": "^3.20.2",
72
- "rollup-plugin-auto-external": "^2.0.0",
73
- "rollup-plugin-dts": "^5.3.0",
74
- "rollup-plugin-esbuild": "^5.0.0",
75
- "rollup-plugin-polyfill-node": "^0.12.0",
76
- "rollup-plugin-visualizer": "^5.9.0",
77
- "standard": "^17.0.0",
78
- "typescript": "^5.0.2",
79
- "vector-storage": "^1.0.55",
80
- "webpack": "^5.78.0",
81
- "webpack-cli": "^5.0.1"
82
- },
83
- "mocha": {
84
- "require": [
85
- "fake-indexeddb/auto"
86
- ]
87
- },
88
- "standard": {
89
- "ignore": [
90
- "examples/**/*.tsx",
91
- "examples/**/dist",
92
- "out/**",
93
- "packages/react/**",
94
- "rollup.config.js"
95
- ]
96
- },
37
+ "homepage": "https://fireproof.storage",
97
38
  "repository": {
98
39
  "type": "git",
99
40
  "url": "git+https://github.com/fireproof-storage/fireproof.git"
@@ -101,22 +42,33 @@
101
42
  "bugs": {
102
43
  "url": "https://github.com/fireproof-storage/fireproof/issues"
103
44
  },
104
- "homepage": "https://fireproof.storage",
105
- "exports": {
106
- ".": {
107
- "types": "./dist/src/fireproof.d.ts",
108
- "import": "./dist/src/fireproof.mjs",
109
- "module": "./dist/src/fireproof.mjs",
110
- "default": "./dist/src/fireproof.js",
111
- "require": "./dist/src/fireproof.js"
112
- },
113
- "./src/*.js": "./src/*.js",
114
- "./src/**/*.js": "./src/**/*.js",
115
- "./package.json": "./package.json"
45
+ "devDependencies": {
46
+ "@types/async": "^3.2.20",
47
+ "@types/mocha": "^10.0.1",
48
+ "@typescript-eslint/eslint-plugin": "^6.1.0",
49
+ "@typescript-eslint/parser": "^6.1.0",
50
+ "browser-assert": "^1.2.1",
51
+ "esbuild": "^0.18.14",
52
+ "esbuild-plugin-polyfill-node": "^0.3.0",
53
+ "esbuild-plugin-tsc": "^0.4.0",
54
+ "eslint": "^8.45.0",
55
+ "eslint-config-standard": "^17.1.0",
56
+ "eslint-plugin-import": "^2.27.5",
57
+ "eslint-plugin-mocha": "^10.1.0",
58
+ "eslint-plugin-node": "^11.1.0",
59
+ "eslint-plugin-promise": "^6.1.1",
60
+ "mocha": "^10.2.0",
61
+ "nodemon": "^3.0.1",
62
+ "polendina": "^3.2.1",
63
+ "tslib": "^2.6.0",
64
+ "typescript": "^5.1.6"
116
65
  },
117
- "files": [
118
- "src",
119
- "dist",
120
- "README.md"
121
- ]
66
+ "dependencies": {
67
+ "@alanshaw/pail": "^0.3.3",
68
+ "@ipld/dag-cbor": "^9.0.3",
69
+ "async": "^3.2.4",
70
+ "idb": "^7.1.1",
71
+ "multiformats": "^12.0.1",
72
+ "prolly-trees": "^1.0.4"
73
+ }
122
74
  }
@@ -1,268 +0,0 @@
1
- import { parse } from 'multiformats/link';
2
- import { CID } from 'multiformats';
3
- import { Valet } from './valet.js';
4
- // const sleep = ms => new Promise(r => setTimeout(r, ms))
5
- const husherMap = new Map();
6
- const husher = (id, workFn) => {
7
- if (!husherMap.has(id)) {
8
- husherMap.set(id, workFn().finally(() => setTimeout(() => husherMap.delete(id), 100)));
9
- }
10
- return husherMap.get(id);
11
- };
12
- /**
13
- * @typedef {{ get: (link: import('../src/link').AnyLink) => Promise<AnyBlock | undefined> }} BlockFetcher
14
- */
15
- /**
16
- * @typedef {Object} AnyBlock
17
- * @property {import('./link').AnyLink} cid - The CID of the block
18
- * @property {Uint8Array} bytes - The block's data
19
- *
20
- * @typedef {Object} Blockstore
21
- * @property {function(import('./link').AnyLink): Promise<AnyBlock|undefined>} get - A function to retrieve a block by CID
22
- * @property {function(import('./link').AnyLink, Uint8Array): Promise<void>} put - A function to store a block's data and CID
23
- *
24
- * A blockstore that caches writes to a transaction and only persists them when committed.
25
- */
26
- export class TransactionBlockstore {
27
- /** @type {Map<string, Uint8Array>} */
28
- committedBlocks = new Map();
29
- /** @type {Valet} */
30
- valet = null;
31
- instanceId = 'blkz.' + Math.random().toString(36).substring(2, 4);
32
- inflightTransactions = new Set();
33
- syncs = new Set();
34
- constructor(name, config) {
35
- if (name) {
36
- this.valet = new Valet(name, config);
37
- this.ready = this.valet.ready;
38
- }
39
- else {
40
- this.ready = Promise.resolve();
41
- }
42
- this.remoteBlockFunction = null;
43
- }
44
- /**
45
- * Get a block from the store.
46
- *
47
- * @param {import('./link').AnyLink} cid
48
- * @returns {Promise<AnyBlock | undefined>}
49
- */
50
- async get(cid) {
51
- const key = cid.toString();
52
- // it is safe to read from the in-flight transactions becauase they are immutable
53
- const bytes = await Promise.any([this.transactionsGet(key), this.committedGet(key)]).catch(e => {
54
- console.log('get error', cid.toString(), e);
55
- return this.networkGet(key);
56
- });
57
- if (!bytes)
58
- throw new Error('Missing block: ' + key);
59
- return { cid, bytes };
60
- }
61
- // this iterates over the in-flight transactions
62
- // and returns the first matching block it finds
63
- async transactionsGet(key) {
64
- for (const transaction of this.inflightTransactions) {
65
- const got = await transaction.get(key);
66
- if (got && got.bytes)
67
- return got.bytes;
68
- }
69
- throw new Error('Missing block: ' + key);
70
- }
71
- async committedGet(key) {
72
- const old = this.committedBlocks.get(key);
73
- // console.log('committedGet: ' + key + ' ' + this.instanceId, old.length)
74
- if (old)
75
- return old;
76
- if (!this.valet)
77
- throw new Error('Missing block: ' + key);
78
- const got = await this.valet.getValetBlock(key);
79
- this.committedBlocks.set(key, got);
80
- return got;
81
- }
82
- async clearCommittedCache() {
83
- this.committedBlocks.clear();
84
- }
85
- async networkGet(key) {
86
- if (this.remoteBlockFunction) {
87
- const value = await husher(key, async () => await this.remoteBlockFunction(key));
88
- if (value) {
89
- // console.log('networkGot: ' + key, value.length)
90
- doTransaction('networkGot: ' + key, this, async (innerBlockstore) => {
91
- await innerBlockstore.put(CID.parse(key), value);
92
- });
93
- return value;
94
- }
95
- }
96
- else {
97
- return false;
98
- }
99
- }
100
- /**
101
- * Add a block to the store. Usually bound to a transaction by a closure.
102
- * It sets the lastCid property to the CID of the block that was put.
103
- * This is used by the transaction as the head of the car when written to the valet.
104
- * We don't have to worry about which transaction we are when we are here because
105
- * we are the transactionBlockstore.
106
- *
107
- * @param {import('./link').AnyLink} cid
108
- * @param {Uint8Array} bytes
109
- */
110
- put(cid, bytes) {
111
- throw new Error('use a transaction to put');
112
- }
113
- /**
114
- * Iterate over all blocks in the store.
115
- *
116
- * @yields {{cid: string, bytes: Uint8Array}}
117
- * @returns {AsyncGenerator<any, any, any>}
118
- */
119
- async *entries() {
120
- for (const transaction of this.inflightTransactions) {
121
- for (const [cid, bytes] of transaction.entries()) { // test for this?
122
- yield { cid: cid.toString(), bytes };
123
- }
124
- }
125
- for (const [str, bytes] of this.committedBlocks) {
126
- yield { cid: str, bytes };
127
- }
128
- if (this.valet) {
129
- for await (const { cid } of this.valet.cids()) {
130
- yield { cid };
131
- }
132
- }
133
- }
134
- /**
135
- * Begin a transaction. Ensures the uncommited blocks are empty at the begining.
136
- * Returns the blocks to read and write during the transaction.
137
- * @returns {InnerBlockstore}
138
- * @memberof TransactionBlockstore
139
- */
140
- begin(label = '') {
141
- const innerTransactionBlockstore = new InnerBlockstore(label, this);
142
- this.inflightTransactions.add(innerTransactionBlockstore);
143
- return innerTransactionBlockstore;
144
- }
145
- /**
146
- * Commit the transaction. Writes the blocks to the store.
147
- * @returns {Promise<void>}
148
- * @memberof TransactionBlockstore
149
- */
150
- async commit(innerBlockstore, doSync = true) {
151
- // console.log('commit', doSync, innerBlockstore.label)
152
- await this.doCommit(innerBlockstore);
153
- if (doSync) {
154
- // const all =
155
- // console.log('syncing', innerBlockstore.label)
156
- await Promise.all([...this.syncs].map(async (sync) => sync.sendUpdate(innerBlockstore).catch(e => {
157
- console.error('sync error, cancelling', e);
158
- sync.destroy();
159
- })));
160
- }
161
- }
162
- // first get the transaction blockstore from the map of transaction blockstores
163
- // then copy it to committedBlocks
164
- // then write the transaction blockstore to a car
165
- // then write the car to the valet
166
- // then remove the transaction blockstore from the map of transaction blockstores
167
- doCommit = async (innerBlockstore) => {
168
- const cids = new Set();
169
- for (const { cid, bytes } of innerBlockstore.entries()) {
170
- const stringCid = cid.toString();
171
- if (this.committedBlocks.has(stringCid)) {
172
- // console.log('Duplicate block: ' + stringCid) // todo some of this can be avoided, cost is extra size on car files
173
- }
174
- else {
175
- this.committedBlocks.set(stringCid, bytes);
176
- cids.add(stringCid);
177
- }
178
- }
179
- // console.log(innerBlockstore.label, 'committing', cids.size, 'blocks', [...cids].map(cid => cid.toString()), this.valet)
180
- if (cids.size > 0 && this.valet) {
181
- await this.valet.writeTransaction(innerBlockstore, cids);
182
- }
183
- };
184
- /**
185
- * Retire the transaction. Clears the uncommited blocks.
186
- * @returns {void}
187
- * @memberof TransactionBlockstore
188
- */
189
- retire(innerBlockstore) {
190
- this.inflightTransactions.delete(innerBlockstore);
191
- }
192
- }
193
- /**
194
- * Runs a function on an inner blockstore, then persists the change to a car writer
195
- * or other outer blockstore.
196
- * @param {string} label
197
- * @param {TransactionBlockstore} blockstore
198
- * @param {(innerBlockstore: Blockstore) => Promise<any>} doFun
199
- * @returns {Promise<any>}
200
- * @memberof TransactionBlockstore
201
- */
202
- export const doTransaction = async (label, blockstore, doFun, doSync = true) => {
203
- // @ts-ignore
204
- if (!blockstore.commit)
205
- return await doFun(blockstore);
206
- // @ts-ignore
207
- const innerBlockstore = blockstore.begin(label);
208
- try {
209
- const result = await doFun(innerBlockstore);
210
- // console.log('doTransaction', label, 'result', result.head)
211
- if (result && result.head) {
212
- innerBlockstore.head = result.head;
213
- }
214
- // pass the latest clock head for writing to the valet
215
- // @ts-ignore
216
- await blockstore.commit(innerBlockstore, doSync);
217
- return result;
218
- }
219
- catch (e) {
220
- console.error(`Transaction ${label} failed`, e, e.stack);
221
- throw e;
222
- }
223
- finally {
224
- // @ts-ignore
225
- blockstore.retire(innerBlockstore);
226
- }
227
- };
228
- export class InnerBlockstore {
229
- /** @type {Map<string, Uint8Array>} */
230
- blocks = new Map();
231
- head = [];
232
- lastCid = null;
233
- label = '';
234
- parentBlockstore = null;
235
- constructor(label, parentBlockstore) {
236
- this.label = label;
237
- this.parentBlockstore = parentBlockstore;
238
- }
239
- /**
240
- * @param {import('./link').AnyLink} cid
241
- * @returns {Promise<AnyBlock | undefined>}
242
- */
243
- async get(cid) {
244
- const key = cid.toString();
245
- let bytes = this.blocks.get(key);
246
- if (bytes) {
247
- return { cid, bytes };
248
- }
249
- bytes = await this.parentBlockstore.committedGet(key);
250
- if (bytes) {
251
- return { cid, bytes };
252
- }
253
- }
254
- /**
255
- * @param {import('./link').AnyLink} cid
256
- * @param {Uint8Array} bytes
257
- */
258
- async put(cid, bytes) {
259
- // console.log('put', cid)
260
- this.blocks.set(cid.toString(), bytes);
261
- this.lastCid = cid;
262
- }
263
- *entries() {
264
- for (const [str, bytes] of this.blocks) {
265
- yield { cid: parse(str), bytes };
266
- }
267
- }
268
- }