@fireproof/core 0.6.4 → 0.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/{src/db-index.js → db-index.js} +11 -1
- package/dist/fireproof.js +90 -0
- package/dist/import.js +29 -0
- package/dist/loader.js +23 -0
- package/dist/src/fireproof.d.ts +1 -1
- package/dist/src/fireproof.js +10 -1
- package/dist/src/fireproof.js.map +1 -1
- package/dist/src/fireproof.mjs +10 -1
- package/dist/src/fireproof.mjs.map +1 -1
- package/dist/storage/base.js +348 -0
- package/dist/storage/browser.js +61 -0
- package/dist/storage/filesystem.js +68 -0
- package/dist/storage/rest.js +58 -0
- package/dist/storage/ucan.js +0 -0
- package/package.json +1 -4
- package/src/db-index.js +10 -1
- package/dist/hooks/use-fireproof.js +0 -150
- package/dist/src/crypto-poly.js +0 -4
- package/dist/src/link.js +0 -1
- package/dist/src/loader.js +0 -131
- package/hooks/use-fireproof.js +0 -173
- /package/dist/{src/blockstore.js → blockstore.js} +0 -0
- /package/dist/{src/clock.js → clock.js} +0 -0
- /package/dist/{src/crypto.js → crypto.js} +0 -0
- /package/dist/{src/database.js → database.js} +0 -0
- /package/dist/{src/listener.js → listener.js} +0 -0
- /package/dist/{src/prolly.js → prolly.js} +0 -0
- /package/dist/{src/sha1.js → sha1.js} +0 -0
- /package/dist/{src/sync.js → sync.js} +0 -0
- /package/dist/{src/utils.js → utils.js} +0 -0
- /package/dist/{src/valet.js → valet.js} +0 -0
package/README.md
CHANGED
@@ -8,8 +8,8 @@
|
|
8
8
|
</h3>
|
9
9
|
|
10
10
|
<p align="center">
|
11
|
-
<a href="https://github.com/
|
12
|
-
<img src="https://github.com/
|
11
|
+
<a href="https://github.com/fireproof-storage/fireproof/actions/workflows/test.yml">
|
12
|
+
<img src="https://github.com/fireproof-storage/fireproof/actions/workflows/test.yml/badge.svg" alt="Test" style="max-width: 100%;">
|
13
13
|
</a>
|
14
14
|
<a href="https://standardjs.com" rel="nofollow">
|
15
15
|
<img src="https://img.shields.io/badge/code_style-standard-brightgreen.svg" alt="JavaScript Style Guide" style="max-width: 100%;">
|
@@ -38,14 +38,14 @@ With Fireproof, you **build first** and connect it to your cloud of choice when
|
|
38
38
|
```js
|
39
39
|
const completedTodos = useLiveQuery((doc) => doc.completed, { key: true })
|
40
40
|
```
|
41
|
-
This is the README for the core database technology. [The `useFireproof` hook documentation has features and a getting started guide](https://github.com/fireproof-storage/fireproof/blob/main/packages/react/README.md), like `
|
41
|
+
This is the README for the core database technology. [The `useFireproof` hook documentation has features and a getting started guide](https://github.com/fireproof-storage/fireproof/blob/main/packages/react/README.md), like `useDocument` and database setup helpers. Don't forget to star 🌟 this repo on the way over.
|
42
42
|
|
43
43
|
## AI Assistant Quick Start
|
44
44
|
|
45
45
|
Because Fireproof is designed around the mantra of build-first, it's ideal for AI-assisted app development as you can get an app up and running before even considering the cloud. If you are using GPT-3.5, GPT-4, or Bard, you can [easily enable the AI to write React apps using Fireproof](https://hackernoon.com/get-chatgpt-to-focus-on-coding-on-the-right-apis-with-gptdoc-strings). Paste this line of code into your prompt, along with a detailed description of the app to build:
|
46
46
|
|
47
47
|
```
|
48
|
-
Fireproof/React/Usage: import { useFireproof } from '@fireproof/react'; function App() { const { useLiveQuery,
|
48
|
+
Fireproof/React/Usage: import { useFireproof } from '@fireproof/react'; function App() { const { useLiveQuery, useDocument, database } = useFireproof(); const result = useLiveQuery(doc => doc.word, { limit: 10 }); const [{ count }, saveCountDocument] = useDocument({_id: 'count', count: 0}); return (<><p>{count} changes</p><input type='text' onChange={() => saveCountDocument({count: count + 1})} onSubmit={e => database.put({word: e.target.value})} /><ul>{result.map(row => (<li key={row.id}>{row.key}</li>))}</ul></>)}
|
49
49
|
```
|
50
50
|
|
51
51
|
Here are some examples that worked for us:
|
@@ -127,13 +127,23 @@ export class DbIndex {
|
|
127
127
|
applyMapFn(mapFn, name) {
|
128
128
|
if (typeof mapFn === 'string') {
|
129
129
|
this.mapFnString = mapFn;
|
130
|
+
// make a regex that matches strings that only have letters, numbers, and spaces
|
131
|
+
const regex = /^[a-zA-Z0-9 ]+$/;
|
132
|
+
// if the string matches the regex, make a function that returns the value at that key
|
133
|
+
if (regex.test(mapFn)) {
|
134
|
+
this.mapFn = (doc, emit) => {
|
135
|
+
if (doc[mapFn])
|
136
|
+
emit(doc[mapFn]);
|
137
|
+
};
|
138
|
+
this.includeDocsDefault = true;
|
139
|
+
}
|
130
140
|
}
|
131
141
|
else {
|
132
142
|
this.mapFn = mapFn;
|
133
143
|
this.mapFnString = mapFn.toString();
|
134
144
|
}
|
135
145
|
const matches = /=>\s*(.*)/.exec(this.mapFnString);
|
136
|
-
this.includeDocsDefault = matches && matches.length > 0;
|
146
|
+
this.includeDocsDefault = this.includeDocsDefault || (matches && matches.length > 0);
|
137
147
|
this.name = name || this.makeName();
|
138
148
|
}
|
139
149
|
makeName() {
|
@@ -0,0 +1,90 @@
|
|
1
|
+
import randomBytes from 'randombytes';
|
2
|
+
import { Database, parseCID } from './database.js';
|
3
|
+
import { Listener } from './listener.js';
|
4
|
+
import { DbIndex as Index } from './db-index.js';
|
5
|
+
// import { TransactionBlockstore } from './blockstore.js'
|
6
|
+
import { localGet } from './utils.js';
|
7
|
+
import { Sync } from './sync.js';
|
8
|
+
// todo remove Listener in 0.7.0
|
9
|
+
export { Index, Listener, Database, Sync };
|
10
|
+
class Fireproof {
|
11
|
+
/**
|
12
|
+
* @function storage
|
13
|
+
* @memberof Fireproof
|
14
|
+
* Creates a new Fireproof instance with default storage settings
|
15
|
+
* Most apps should use this and not worry about the details.
|
16
|
+
* @static
|
17
|
+
* @returns {Database} - a new Fireproof instance
|
18
|
+
*/
|
19
|
+
static storage = (name = null, opts = {}) => {
|
20
|
+
if (name) {
|
21
|
+
opts.name = name;
|
22
|
+
// todo this can come from a registry also eg remote database / config, etc
|
23
|
+
const existing = localGet('fp.' + name);
|
24
|
+
if (existing) {
|
25
|
+
const existingConfig = JSON.parse(existing);
|
26
|
+
return Fireproof.fromConfig(name, existingConfig, opts);
|
27
|
+
}
|
28
|
+
else {
|
29
|
+
const instanceKey = randomBytes(32).toString('hex'); // pass null to disable encryption
|
30
|
+
opts.key = instanceKey;
|
31
|
+
return new Database(name, [], opts);
|
32
|
+
}
|
33
|
+
}
|
34
|
+
else {
|
35
|
+
return new Database(null, [], opts);
|
36
|
+
}
|
37
|
+
};
|
38
|
+
static fromConfig(name, existingConfig, opts = {}) {
|
39
|
+
opts.key = existingConfig.key;
|
40
|
+
const fp = new Database(name, [], opts);
|
41
|
+
return Fireproof.fromJSON(existingConfig, fp);
|
42
|
+
}
|
43
|
+
static fromJSON(json, database) {
|
44
|
+
database.hydrate({ car: json.car, indexCar: json.indexCar, clock: json.clock.map(c => parseCID(c)), name: json.name, key: json.key });
|
45
|
+
if (json.indexes) {
|
46
|
+
for (const { name, code, clock: { byId, byKey, db } } of json.indexes) {
|
47
|
+
Index.fromJSON(database, {
|
48
|
+
clock: {
|
49
|
+
byId: byId ? parseCID(byId) : null,
|
50
|
+
byKey: byKey ? parseCID(byKey) : null,
|
51
|
+
db: (db && db.length > 0) ? db.map(c => parseCID(c)) : null
|
52
|
+
},
|
53
|
+
code,
|
54
|
+
name
|
55
|
+
});
|
56
|
+
}
|
57
|
+
}
|
58
|
+
return database;
|
59
|
+
}
|
60
|
+
static snapshot(database, clock) {
|
61
|
+
const definition = database.toJSON();
|
62
|
+
const withBlocks = new Database(database.name);
|
63
|
+
withBlocks.blocks = database.blocks;
|
64
|
+
if (clock) {
|
65
|
+
definition.clock = clock.map(c => parseCID(c));
|
66
|
+
definition.indexes.forEach(index => {
|
67
|
+
index.clock.byId = null;
|
68
|
+
index.clock.byKey = null;
|
69
|
+
index.clock.db = null;
|
70
|
+
});
|
71
|
+
}
|
72
|
+
const snappedDb = Fireproof.fromJSON(definition, withBlocks);
|
73
|
+
[...database.indexes.values()].forEach(index => {
|
74
|
+
snappedDb.indexes.get(index.mapFnString).mapFn = index.mapFn;
|
75
|
+
});
|
76
|
+
return snappedDb;
|
77
|
+
}
|
78
|
+
static async zoom(database, clock) {
|
79
|
+
;
|
80
|
+
[...database.indexes.values()].forEach(index => {
|
81
|
+
index.indexById = { root: null, cid: null };
|
82
|
+
index.indexByKey = { root: null, cid: null };
|
83
|
+
index.dbHead = null;
|
84
|
+
});
|
85
|
+
database.clock = clock.map(c => parseCID(c));
|
86
|
+
await database.notifyReset(); // hmm... indexes should listen to this? might be more complex than worth it. so far this is the only caller
|
87
|
+
return database;
|
88
|
+
}
|
89
|
+
}
|
90
|
+
export { Fireproof };
|
package/dist/import.js
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
import { createReadStream } from 'fs';
|
2
|
+
import { join } from 'path';
|
3
|
+
import { parse } from '@jsonlines/core';
|
4
|
+
import cargoQueue from 'async/cargoQueue.js';
|
5
|
+
// todo maybe this goes in a utils package for tree-shaking?
|
6
|
+
async function loadData(database, filename) {
|
7
|
+
const fullFilePath = join(process.cwd(), filename);
|
8
|
+
const readableStream = createReadStream(fullFilePath);
|
9
|
+
const parseStream = parse();
|
10
|
+
readableStream.pipe(parseStream);
|
11
|
+
const saveQueue = cargoQueue(async (tasks, callback) => {
|
12
|
+
for (const t of tasks) {
|
13
|
+
await database.put(t);
|
14
|
+
}
|
15
|
+
callback();
|
16
|
+
});
|
17
|
+
parseStream.on('data', async (data) => {
|
18
|
+
saveQueue.push(data);
|
19
|
+
});
|
20
|
+
let res;
|
21
|
+
const p = new Promise((resolve, reject) => {
|
22
|
+
res = resolve;
|
23
|
+
});
|
24
|
+
saveQueue.drain(async (x) => {
|
25
|
+
res();
|
26
|
+
});
|
27
|
+
return p;
|
28
|
+
}
|
29
|
+
export { loadData };
|
package/dist/loader.js
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
import { Browser } from './storage/browser.js';
|
2
|
+
import { Filesystem } from './storage/filesystem.js';
|
3
|
+
import { Rest } from './storage/rest.js';
|
4
|
+
const FORCE_IDB = typeof process !== 'undefined' && !!process.env?.FORCE_IDB;
|
5
|
+
/* global window */
|
6
|
+
export const Loader = {
|
7
|
+
appropriate: (name, config = {}) => {
|
8
|
+
let isBrowser = false;
|
9
|
+
try {
|
10
|
+
isBrowser = window.localStorage && true;
|
11
|
+
}
|
12
|
+
catch (e) { }
|
13
|
+
if (config.type === 'rest') {
|
14
|
+
return new Rest(name, config);
|
15
|
+
}
|
16
|
+
if (FORCE_IDB || isBrowser) {
|
17
|
+
return new Browser(name, config);
|
18
|
+
}
|
19
|
+
else {
|
20
|
+
return new Filesystem(name, config);
|
21
|
+
}
|
22
|
+
}
|
23
|
+
};
|
package/dist/src/fireproof.d.ts
CHANGED
package/dist/src/fireproof.js
CHANGED
@@ -41711,12 +41711,21 @@ class DbIndex {
|
|
41711
41711
|
applyMapFn (mapFn, name) {
|
41712
41712
|
if (typeof mapFn === 'string') {
|
41713
41713
|
this.mapFnString = mapFn;
|
41714
|
+
// make a regex that matches strings that only have letters, numbers, and spaces
|
41715
|
+
const regex = /^[a-zA-Z0-9 ]+$/;
|
41716
|
+
// if the string matches the regex, make a function that returns the value at that key
|
41717
|
+
if (regex.test(mapFn)) {
|
41718
|
+
this.mapFn = (doc, emit) => {
|
41719
|
+
if (doc[mapFn]) emit(doc[mapFn]);
|
41720
|
+
};
|
41721
|
+
this.includeDocsDefault = true;
|
41722
|
+
}
|
41714
41723
|
} else {
|
41715
41724
|
this.mapFn = mapFn;
|
41716
41725
|
this.mapFnString = mapFn.toString();
|
41717
41726
|
}
|
41718
41727
|
const matches = /=>\s*(.*)/.exec(this.mapFnString);
|
41719
|
-
this.includeDocsDefault = matches && matches.length > 0;
|
41728
|
+
this.includeDocsDefault = this.includeDocsDefault || (matches && matches.length > 0);
|
41720
41729
|
this.name = name || this.makeName();
|
41721
41730
|
}
|
41722
41731
|
|