mindoodb 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -24
- package/dist/__mocks__/expo-standard-web-crypto.d.ts +10 -0
- package/dist/__mocks__/expo-standard-web-crypto.d.ts.map +1 -0
- package/dist/__mocks__/expo-standard-web-crypto.js +22 -0
- package/dist/__mocks__/expo-standard-web-crypto.js.map +1 -0
- package/dist/appendonlystores/BasicOnDiskContentAddressedStoreFactory.d.ts +8 -0
- package/dist/appendonlystores/BasicOnDiskContentAddressedStoreFactory.d.ts.map +1 -0
- package/dist/appendonlystores/BasicOnDiskContentAddressedStoreFactory.js +16 -0
- package/dist/appendonlystores/BasicOnDiskContentAddressedStoreFactory.js.map +1 -0
- package/dist/appendonlystores/InMemoryContentAddressedStoreFactory.d.ts +1 -1
- package/dist/appendonlystores/InMemoryContentAddressedStoreFactory.d.ts.map +1 -1
- package/dist/appendonlystores/InMemoryContentAddressedStoreFactory.js +2 -2
- package/dist/appendonlystores/InMemoryContentAddressedStoreFactory.js.map +1 -1
- package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.d.ts +19 -2
- package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.d.ts.map +1 -1
- package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js +133 -22
- package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js.map +1 -1
- package/dist/appendonlystores/network/HttpTransport.d.ts +20 -3
- package/dist/appendonlystores/network/HttpTransport.d.ts.map +1 -1
- package/dist/appendonlystores/network/HttpTransport.js +136 -21
- package/dist/appendonlystores/network/HttpTransport.js.map +1 -1
- package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts +33 -3
- package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts.map +1 -1
- package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.js +148 -27
- package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.js.map +1 -1
- package/dist/appendonlystores/network/index.d.ts +1 -1
- package/dist/appendonlystores/network/index.d.ts.map +1 -1
- package/dist/appendonlystores/network/index.js.map +1 -1
- package/dist/browser/appendonlystores/IndexedDBContentAddressedStore.d.ts +61 -0
- package/dist/browser/appendonlystores/IndexedDBContentAddressedStore.d.ts.map +1 -0
- package/dist/browser/appendonlystores/IndexedDBContentAddressedStore.js +685 -0
- package/dist/browser/appendonlystores/IndexedDBContentAddressedStore.js.map +1 -0
- package/dist/browser/appendonlystores/IndexedDBContentAddressedStoreFactory.d.ts +25 -0
- package/dist/browser/appendonlystores/IndexedDBContentAddressedStoreFactory.d.ts.map +1 -0
- package/dist/browser/appendonlystores/IndexedDBContentAddressedStoreFactory.js +41 -0
- package/dist/browser/appendonlystores/IndexedDBContentAddressedStoreFactory.js.map +1 -0
- package/dist/browser/index.d.ts +5 -0
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +13 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/core/BaseMindooDB.d.ts +38 -4
- package/dist/core/BaseMindooDB.d.ts.map +1 -1
- package/dist/core/BaseMindooDB.js +810 -329
- package/dist/core/BaseMindooDB.js.map +1 -1
- package/dist/core/BaseMindooTenant.d.ts +42 -6
- package/dist/core/BaseMindooTenant.d.ts.map +1 -1
- package/dist/core/BaseMindooTenant.js +259 -93
- package/dist/core/BaseMindooTenant.js.map +1 -1
- package/dist/core/BaseMindooTenantDirectory.d.ts +3 -1
- package/dist/core/BaseMindooTenantDirectory.d.ts.map +1 -1
- package/dist/core/BaseMindooTenantDirectory.js +50 -40
- package/dist/core/BaseMindooTenantDirectory.js.map +1 -1
- package/dist/core/BaseMindooTenantFactory.d.ts +25 -29
- package/dist/core/BaseMindooTenantFactory.d.ts.map +1 -1
- package/dist/core/BaseMindooTenantFactory.js +175 -73
- package/dist/core/BaseMindooTenantFactory.js.map +1 -1
- package/dist/core/appendonlystores/BasicOnDiskContentAddressedStore.d.ts +68 -0
- package/dist/core/appendonlystores/BasicOnDiskContentAddressedStore.d.ts.map +1 -0
- package/dist/core/appendonlystores/BasicOnDiskContentAddressedStore.js +659 -0
- package/dist/core/appendonlystores/BasicOnDiskContentAddressedStore.js.map +1 -0
- package/dist/core/appendonlystores/InMemoryContentAddressedStore.d.ts +50 -4
- package/dist/core/appendonlystores/InMemoryContentAddressedStore.d.ts.map +1 -1
- package/dist/core/appendonlystores/InMemoryContentAddressedStore.js +204 -39
- package/dist/core/appendonlystores/InMemoryContentAddressedStore.js.map +1 -1
- package/dist/core/appendonlystores/bloom.d.ts +85 -0
- package/dist/core/appendonlystores/bloom.d.ts.map +1 -0
- package/dist/core/appendonlystores/bloom.js +228 -0
- package/dist/core/appendonlystores/bloom.js.map +1 -0
- package/dist/core/appendonlystores/network/AuthenticationService.d.ts +3 -0
- package/dist/core/appendonlystores/network/AuthenticationService.d.ts.map +1 -1
- package/dist/core/appendonlystores/network/AuthenticationService.js +21 -17
- package/dist/core/appendonlystores/network/AuthenticationService.js.map +1 -1
- package/dist/core/appendonlystores/network/NetworkTransport.d.ts +36 -2
- package/dist/core/appendonlystores/network/NetworkTransport.d.ts.map +1 -1
- package/dist/core/appendonlystores/network/types.d.ts +10 -0
- package/dist/core/appendonlystores/network/types.d.ts.map +1 -1
- package/dist/core/appendonlystores/network/types.js.map +1 -1
- package/dist/core/appendonlystores/types.d.ts +137 -1
- package/dist/core/appendonlystores/types.d.ts.map +1 -1
- package/dist/core/automerge-adapter.d.ts +15 -0
- package/dist/core/automerge-adapter.d.ts.map +1 -0
- package/dist/core/automerge-adapter.js +73 -0
- package/dist/core/automerge-adapter.js.map +1 -0
- package/dist/core/crypto/MindooDocSigner.d.ts +3 -1
- package/dist/core/crypto/MindooDocSigner.d.ts.map +1 -1
- package/dist/core/crypto/MindooDocSigner.js +9 -5
- package/dist/core/crypto/MindooDocSigner.js.map +1 -1
- package/dist/core/crypto/RSAEncryption.d.ts +3 -1
- package/dist/core/crypto/RSAEncryption.d.ts.map +1 -1
- package/dist/core/crypto/RSAEncryption.js +13 -9
- package/dist/core/crypto/RSAEncryption.js.map +1 -1
- package/dist/core/crypto/pbkdf2Iterations.d.ts +12 -0
- package/dist/core/crypto/pbkdf2Iterations.d.ts.map +1 -0
- package/dist/core/crypto/pbkdf2Iterations.js +55 -0
- package/dist/core/crypto/pbkdf2Iterations.js.map +1 -0
- package/dist/core/index.d.ts +7 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +30 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/indexing/virtualviews/MindooDBVirtualViewDataProvider.d.ts +1 -1
- package/dist/core/indexing/virtualviews/MindooDBVirtualViewDataProvider.js +2 -2
- package/dist/core/indexing/virtualviews/MindooDBVirtualViewDataProvider.js.map +1 -1
- package/dist/core/indexing/virtualviews/index.d.ts +1 -1
- package/dist/core/indexing/virtualviews/index.js +1 -1
- package/dist/core/keys/KeyBag.d.ts +36 -13
- package/dist/core/keys/KeyBag.d.ts.map +1 -1
- package/dist/core/keys/KeyBag.js +96 -31
- package/dist/core/keys/KeyBag.js.map +1 -1
- package/dist/core/keys/KeyContext.d.ts +4 -0
- package/dist/core/keys/KeyContext.d.ts.map +1 -0
- package/dist/core/keys/KeyContext.js +11 -0
- package/dist/core/keys/KeyContext.js.map +1 -0
- package/dist/core/logging/LogLevel.d.ts +21 -0
- package/dist/core/logging/LogLevel.d.ts.map +1 -0
- package/dist/core/logging/LogLevel.js +56 -0
- package/dist/core/logging/LogLevel.js.map +1 -0
- package/dist/core/logging/Logger.d.ts +37 -0
- package/dist/core/logging/Logger.d.ts.map +1 -0
- package/dist/core/logging/Logger.js +3 -0
- package/dist/core/logging/Logger.js.map +1 -0
- package/dist/core/logging/MindooLogger.d.ts +28 -0
- package/dist/core/logging/MindooLogger.d.ts.map +1 -0
- package/dist/core/logging/MindooLogger.js +217 -0
- package/dist/core/logging/MindooLogger.js.map +1 -0
- package/dist/core/logging/index.d.ts +4 -0
- package/dist/core/logging/index.d.ts.map +1 -0
- package/dist/core/logging/index.js +10 -0
- package/dist/core/logging/index.js.map +1 -0
- package/dist/core/types.d.ts +313 -77
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -1
- package/dist/core/uri/MindooURI.d.ts +58 -0
- package/dist/core/uri/MindooURI.d.ts.map +1 -0
- package/dist/core/uri/MindooURI.js +169 -0
- package/dist/core/uri/MindooURI.js.map +1 -0
- package/dist/core/userid/index.d.ts +0 -10
- package/dist/core/userid/index.d.ts.map +1 -1
- package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.d.ts +541 -0
- package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.d.ts.map +1 -0
- package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.js +1334 -0
- package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.js.map +1 -0
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +5 -1
- package/dist/node/index.js.map +1 -1
- package/dist/reactnative/crypto/AESAdapter.d.ts +18 -0
- package/dist/reactnative/crypto/AESAdapter.d.ts.map +1 -0
- package/dist/reactnative/crypto/AESAdapter.js +112 -0
- package/dist/reactnative/crypto/AESAdapter.js.map +1 -0
- package/dist/reactnative/crypto/Ed25519Adapter.d.ts +34 -0
- package/dist/reactnative/crypto/Ed25519Adapter.d.ts.map +1 -0
- package/dist/reactnative/crypto/Ed25519Adapter.js +386 -0
- package/dist/reactnative/crypto/Ed25519Adapter.js.map +1 -0
- package/dist/reactnative/crypto/ExpoGoCryptoAdapter.d.ts +23 -0
- package/dist/reactnative/crypto/ExpoGoCryptoAdapter.d.ts.map +1 -0
- package/dist/reactnative/crypto/ExpoGoCryptoAdapter.js +51 -0
- package/dist/reactnative/crypto/ExpoGoCryptoAdapter.js.map +1 -0
- package/dist/reactnative/crypto/HMACAdapter.d.ts +13 -0
- package/dist/reactnative/crypto/HMACAdapter.d.ts.map +1 -0
- package/dist/reactnative/crypto/HMACAdapter.js +50 -0
- package/dist/reactnative/crypto/HMACAdapter.js.map +1 -0
- package/dist/reactnative/crypto/KeyFormatConverter.d.ts +21 -0
- package/dist/reactnative/crypto/KeyFormatConverter.d.ts.map +1 -0
- package/dist/reactnative/crypto/KeyFormatConverter.js +72 -0
- package/dist/reactnative/crypto/KeyFormatConverter.js.map +1 -0
- package/dist/reactnative/crypto/PBKDF2Adapter.d.ts +19 -0
- package/dist/reactnative/crypto/PBKDF2Adapter.d.ts.map +1 -0
- package/dist/reactnative/crypto/PBKDF2Adapter.js +67 -0
- package/dist/reactnative/crypto/PBKDF2Adapter.js.map +1 -0
- package/dist/reactnative/crypto/QuickCryptoAdapter.d.ts +37 -0
- package/dist/reactnative/crypto/QuickCryptoAdapter.d.ts.map +1 -0
- package/dist/reactnative/crypto/QuickCryptoAdapter.js +72 -0
- package/dist/reactnative/crypto/QuickCryptoAdapter.js.map +1 -0
- package/dist/reactnative/crypto/RSAAdapter.d.ts +38 -0
- package/dist/reactnative/crypto/RSAAdapter.d.ts.map +1 -0
- package/dist/reactnative/crypto/RSAAdapter.js +184 -0
- package/dist/reactnative/crypto/RSAAdapter.js.map +1 -0
- package/dist/reactnative/crypto/ReactNativeCryptoAdapter.d.ts +33 -0
- package/dist/reactnative/crypto/ReactNativeCryptoAdapter.d.ts.map +1 -0
- package/dist/reactnative/crypto/ReactNativeCryptoAdapter.js +61 -0
- package/dist/reactnative/crypto/ReactNativeCryptoAdapter.js.map +1 -0
- package/dist/reactnative/crypto/SHA256Adapter.d.ts +9 -0
- package/dist/reactnative/crypto/SHA256Adapter.d.ts.map +1 -0
- package/dist/reactnative/crypto/SHA256Adapter.js +29 -0
- package/dist/reactnative/crypto/SHA256Adapter.js.map +1 -0
- package/dist/reactnative/crypto/SubtleCryptoPolyfill.d.ts +63 -0
- package/dist/reactnative/crypto/SubtleCryptoPolyfill.d.ts.map +1 -0
- package/dist/reactnative/crypto/SubtleCryptoPolyfill.js +350 -0
- package/dist/reactnative/crypto/SubtleCryptoPolyfill.js.map +1 -0
- package/dist/reactnative/index.d.ts +8 -0
- package/dist/reactnative/index.d.ts.map +1 -0
- package/dist/reactnative/index.js +38 -0
- package/dist/reactnative/index.js.map +1 -0
- package/package.json +51 -6
- package/patches/PATCHES.md +111 -0
- package/patches/react-native+0.76.9.patch +34 -0
- package/patches/react-native-quick-crypto+1.0.7.patch +42 -0
- package/scripts/cli.js +21 -0
- package/scripts/setup-react-native.js +228 -0
- package/templates/reactnative/App.js +252 -0
- package/templates/reactnative/app.json +29 -0
- package/templates/reactnative/babel.config.js +6 -0
- package/templates/reactnative/index.js +26 -0
- package/templates/reactnative/metro.config.snippet.js +39 -0
- package/templates/reactnative/mindoodb-polyfills.js +116 -0
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ Traditional databases trust the server. If your hosting provider is compromised,
|
|
|
44
44
|
└──────────────────────────────────────────────────────────────────┘
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
**Sync happens through content-addressed stores**: clients exchange only the encrypted entries they're missing. Works peer-to-peer, client-server, or any combination.
|
|
47
|
+
**Sync happens through content-addressed stores**: clients exchange only the encrypted entries they're missing. Works peer-to-peer, client-server, or any combination - for documents and attached files.
|
|
48
48
|
|
|
49
49
|
## Key Features
|
|
50
50
|
|
|
@@ -65,37 +65,58 @@ Traditional databases trust the server. If your hosting provider is compromised,
|
|
|
65
65
|
npm install mindoodb
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
+
> 📱 **React Native / Expo?** See the [React Native setup guide](./docs/reactnative.md) for mobile-specific instructions with native performance.
|
|
69
|
+
|
|
70
|
+
### Pick Your Runtime
|
|
71
|
+
|
|
72
|
+
| Runtime | Fastest start | Recommended path |
|
|
73
|
+
|---------|---------------|------------------|
|
|
74
|
+
| Node.js | Use `mindoodb` directly in a Node script | [Getting Started](./docs/getting-started.md#nodejs) |
|
|
75
|
+
| Web | Import from `mindoodb/browser` | [Getting Started](./docs/getting-started.md#web-browser) |
|
|
76
|
+
| React Native / Expo | Run `npx mindoodb setup-react-native` in your app root | [React Native Guide](./docs/reactnative.md) |
|
|
77
|
+
|
|
78
|
+
### React Native Recommendation
|
|
79
|
+
|
|
80
|
+
- Use **native Automerge** (`react-native-automerge-generated`) and native crypto for production.
|
|
81
|
+
- Treat Expo Go / JS fallback as a convenience path for prototyping, not the default production runtime.
|
|
82
|
+
|
|
68
83
|
### Create a Tenant and Start Working
|
|
69
84
|
|
|
70
85
|
```typescript
|
|
71
86
|
import {
|
|
72
87
|
BaseMindooTenantFactory,
|
|
73
|
-
|
|
74
|
-
KeyBag
|
|
88
|
+
InMemoryContentAddressedStoreFactory,
|
|
89
|
+
KeyBag,
|
|
90
|
+
PUBLIC_INFOS_KEY_ID
|
|
75
91
|
} from "mindoodb";
|
|
76
92
|
|
|
77
93
|
// 1. Set up storage (in-memory for demo; use file/server-backed for production)
|
|
78
|
-
const storeFactory = new
|
|
94
|
+
const storeFactory = new InMemoryContentAddressedStoreFactory();
|
|
79
95
|
const factory = new BaseMindooTenantFactory(storeFactory);
|
|
80
96
|
|
|
81
97
|
// 2. Create a user (generates signing + encryption key pairs)
|
|
82
98
|
const user = await factory.createUserId("CN=alice/O=acme", "user-password");
|
|
83
99
|
const keyBag = new KeyBag(user.userEncryptionKeyPair.privateKey, "user-password");
|
|
84
100
|
|
|
85
|
-
// 3. Create admin keys
|
|
86
|
-
const
|
|
101
|
+
// 3. Create admin user (signing + encryption keys used for tenant administration)
|
|
102
|
+
const adminUser = await factory.createUserId("CN=admin/O=acme", "admin-password");
|
|
103
|
+
|
|
104
|
+
// 4. Create required tenant keys directly in KeyBag (canonical key source)
|
|
105
|
+
const tenantId = "acme-corp";
|
|
106
|
+
await keyBag.createTenantKey(tenantId);
|
|
107
|
+
await keyBag.createDocKey(PUBLIC_INFOS_KEY_ID);
|
|
87
108
|
|
|
88
|
-
//
|
|
89
|
-
const tenant = await factory.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
109
|
+
// 5. Open tenant
|
|
110
|
+
const tenant = await factory.openTenant(
|
|
111
|
+
tenantId,
|
|
112
|
+
adminUser.userSigningKeyPair.publicKey,
|
|
113
|
+
adminUser.userEncryptionKeyPair.publicKey,
|
|
93
114
|
user,
|
|
94
115
|
"user-password",
|
|
95
116
|
keyBag
|
|
96
117
|
);
|
|
97
118
|
|
|
98
|
-
//
|
|
119
|
+
// 6. Open a database and create documents
|
|
99
120
|
const db = await tenant.openDB("contacts");
|
|
100
121
|
const doc = await db.createDocument();
|
|
101
122
|
|
|
@@ -105,7 +126,7 @@ await db.changeDoc(doc, async (d) => {
|
|
|
105
126
|
data.email = "john@example.com";
|
|
106
127
|
});
|
|
107
128
|
|
|
108
|
-
//
|
|
129
|
+
// 7. Read it back
|
|
109
130
|
const contacts = await db.getAllDocumentIds();
|
|
110
131
|
const loaded = await db.getDocument(contacts[0]);
|
|
111
132
|
console.log(loaded.getData()); // { name: "John Doe", email: "john@example.com" }
|
|
@@ -158,7 +179,7 @@ A special **directory** database stores user registrations (admin-only).
|
|
|
158
179
|
[Automerge](https://automerge.org/) CRDTs with full history:
|
|
159
180
|
- Every change is signed and encrypted
|
|
160
181
|
- Automatic conflict resolution for concurrent edits
|
|
161
|
-
- Time travel: reconstruct any historical state of documents (e.g. run queries on historic data)
|
|
182
|
+
- Time travel: reconstruct any historical state of documents (e.g. run queries on historic data) — see [Time Travel Documentation](./docs/timetravel.md)
|
|
162
183
|
|
|
163
184
|
### Attachments
|
|
164
185
|
Files attached to documents:
|
|
@@ -179,15 +200,14 @@ MindooDB provides a flexible, **incremental indexing** facility:
|
|
|
179
200
|
// Incremental indexing: process only what's new
|
|
180
201
|
let cursor = null;
|
|
181
202
|
while (true) {
|
|
182
|
-
const {
|
|
183
|
-
for (const doc of documents) {
|
|
203
|
+
for await (const { doc, cursor: newCursor } of db.iterateChangesSince(cursor)) {
|
|
184
204
|
if (doc.isDeleted()) {
|
|
185
|
-
mySearchIndex.remove(doc.
|
|
205
|
+
mySearchIndex.remove(doc.getId());
|
|
186
206
|
} else {
|
|
187
207
|
mySearchIndex.update(doc); // Flexsearch, Lunr, or custom
|
|
188
208
|
}
|
|
209
|
+
cursor = newCursor;
|
|
189
210
|
}
|
|
190
|
-
cursor = newCursor;
|
|
191
211
|
await sleep(1000);
|
|
192
212
|
}
|
|
193
213
|
```
|
|
@@ -201,20 +221,20 @@ All encryption keys are stored in the **KeyBag**—a local, password-protected k
|
|
|
201
221
|
| **`default` key** | Used when no other key is specified | All tenant members |
|
|
202
222
|
| **Named keys** | Fine-grained access for sensitive docs | Only users you share it with |
|
|
203
223
|
|
|
204
|
-
Keys are distributed offline (email
|
|
224
|
+
Keys are distributed offline (e.g. password protected via email or a shared drive). The `default` key is typically shared during onboarding; named keys are shared as needed for specific documents.
|
|
205
225
|
|
|
206
226
|
## Security
|
|
207
227
|
|
|
208
228
|
### Cryptographic Guarantees
|
|
209
|
-
- **Signatures**: Ed25519 on every change
|
|
210
|
-
- **Encryption**: AES-256-GCM
|
|
211
|
-
- **Integrity**: Changes are hash-chained
|
|
229
|
+
- **Signatures**: Ed25519 on every change - proves who wrote it
|
|
230
|
+
- **Encryption**: AES-256-GCM - servers see only ciphertext
|
|
231
|
+
- **Integrity**: Changes are hash-chained - tampering breaks the chain
|
|
212
232
|
|
|
213
233
|
### User Revocation
|
|
214
234
|
Revoked users:
|
|
215
235
|
- ❌ Cannot sync with peers or servers
|
|
216
236
|
- ❌ Cannot make new changes (signatures rejected)
|
|
217
|
-
- ⚠️ Can
|
|
237
|
+
- ⚠️ Can currently read previously-synced local data (planned: data wipe on first connect after revocation)
|
|
218
238
|
|
|
219
239
|
MindooDB includes **revocation timestamp protection** to prevent backdated changes from revoked users. See: [Revocation Protection](./docs/revocation-timestamp-protection.md)
|
|
220
240
|
|
|
@@ -224,6 +244,13 @@ Append-only storage means nothing is ever deleted:
|
|
|
224
244
|
- Cryptographic proof of all operations
|
|
225
245
|
- GDPR compliance via `purgeDocHistory()` when legally required
|
|
226
246
|
|
|
247
|
+
## Supported Platforms
|
|
248
|
+
|
|
249
|
+
- ✅ **Node.js** - Server-side and desktop apps
|
|
250
|
+
- ✅ **Web Browsers** - Progressive web apps with Web Crypto API
|
|
251
|
+
- ✅ **React Native / Expo** - iOS and Android with native Automerge (Rust via JSI)
|
|
252
|
+
- ✅ **Electron** - Cross-platform desktop apps
|
|
253
|
+
|
|
227
254
|
## Use Cases
|
|
228
255
|
|
|
229
256
|
- **Multi-Tenant SaaS**: Each customer isolated with encrypted data
|
|
@@ -231,20 +258,66 @@ Append-only storage means nothing is ever deleted:
|
|
|
231
258
|
- **Secure File Sharing**: Named keys for need-to-know access
|
|
232
259
|
- **Audit-Critical Systems**: Tamperproof history meets compliance requirements
|
|
233
260
|
- **Offline-First Apps**: Full functionality without network; sync when connected
|
|
261
|
+
- **Mobile Apps**: End-to-end encrypted sync with native performance
|
|
234
262
|
|
|
235
263
|
See: [Use Cases Documentation](./docs/usecases/README.md)
|
|
236
264
|
|
|
237
265
|
## Documentation
|
|
238
266
|
|
|
267
|
+
- [Getting Started](./docs/getting-started.md) — Fast setup for Node.js, Web, and React Native
|
|
268
|
+
- [Example Snippets](./docs/examples/README.md) — Copy-paste Todo starters for all runtimes
|
|
239
269
|
- [Architecture Specification](./docs/specification.md) — Full technical details
|
|
270
|
+
- [React Native Guide](./docs/reactnative.md) — Native Automerge setup and troubleshooting
|
|
240
271
|
- [Virtual Views](./docs/virtualview.md) — Aggregations and cross-database views
|
|
241
272
|
- [Data Indexing](./docs/dataindexing.md) — Incremental indexing and search integration
|
|
273
|
+
- [Time Travel](./docs/timetravel.md) — Historical document retrieval and history traversal
|
|
242
274
|
- [P2P Sync](./docs/p2psync.md) — Peer-to-peer synchronization
|
|
243
275
|
- [Attachments](./docs/attachments.md) — File storage and streaming
|
|
244
276
|
|
|
277
|
+
## Testing
|
|
278
|
+
|
|
279
|
+
Run tests from the command line:
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
# Node.js unit/integration tests (Jest)
|
|
283
|
+
npm test
|
|
284
|
+
|
|
285
|
+
# Install Chromium once for browser tests
|
|
286
|
+
npm run test:browser:install
|
|
287
|
+
|
|
288
|
+
# Real browser runtime tests (Playwright + headless Chromium)
|
|
289
|
+
npm run test:browser
|
|
290
|
+
|
|
291
|
+
# Run Node + browser lanes
|
|
292
|
+
npm run test:all
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Test coverage by environment
|
|
296
|
+
|
|
297
|
+
| Environment | Command | What is covered today |
|
|
298
|
+
|-------------|---------|------------------------|
|
|
299
|
+
| Node.js | `npm test` | Full Jest suite for core APIs (documents, sync logic, indexing, virtual views, settings, trust model, attachments, etc.) |
|
|
300
|
+
| Browser | `npm run test:browser` | Real Chromium runtime via Playwright, including browser entrypoint usage, document lifecycle, real HTTP sync endpoint flows, and browser Virtual View update behavior |
|
|
301
|
+
| React Native / Expo | `npm test -- ReactNativeCrypto.test.ts` | Crypto adapter behavior in Jest (uses `src/__mocks__/expo-standard-web-crypto.ts`), not a device/simulator E2E run |
|
|
302
|
+
|
|
303
|
+
### Browser sync test behavior
|
|
304
|
+
|
|
305
|
+
- Browser tests run in headless Chromium and execute MindooDB browser code in a real page runtime.
|
|
306
|
+
- During test setup, an ephemeral HTTP server is started automatically and exposes the real sync endpoints.
|
|
307
|
+
- Sync assertions use real HTTP requests against that temporary endpoint (no mocked transport for sync tests).
|
|
308
|
+
- The server binds to an OS-assigned free port and is shut down after the suite completes.
|
|
309
|
+
|
|
310
|
+
### Current parity status
|
|
311
|
+
|
|
312
|
+
- The package exports and core API shape are aligned across Node.js, browser, and React Native entrypoints.
|
|
313
|
+
- Node and browser now have executable CLI lanes with runtime validation.
|
|
314
|
+
- React Native coverage is currently adapter-focused in Jest and does not yet validate full app-level behavior inside a real React Native runtime.
|
|
315
|
+
- For high confidence in three-environment parity, add a React Native integration lane (Expo/Detox or RN test app) that exercises document lifecycle, sync, and virtual view updates on device/simulator.
|
|
316
|
+
- For Expo Go / JS fallback scenarios, PBKDF2 iterations can be tuned at runtime; native RN builds should keep strong defaults.
|
|
317
|
+
|
|
245
318
|
## Support
|
|
246
319
|
|
|
247
|
-
Need
|
|
320
|
+
Need commercial support, have questions, or want to request a feature? We're here to help! :-)
|
|
248
321
|
|
|
249
322
|
- 🐛 **Bug Reports**: [Open an issue on GitHub](https://github.com/klehmann/mindoodb/issues)
|
|
250
323
|
- 💬 **Questions & Discussions**: [GitHub Discussions](https://github.com/klehmann/mindoodb/discussions)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock for expo-standard-web-crypto
|
|
3
|
+
* Uses Node.js crypto for getRandomValues in tests
|
|
4
|
+
*/
|
|
5
|
+
export declare function getRandomValues(array: Uint8Array): Uint8Array;
|
|
6
|
+
declare const _default: {
|
|
7
|
+
getRandomValues: typeof getRandomValues;
|
|
8
|
+
};
|
|
9
|
+
export default _default;
|
|
10
|
+
//# sourceMappingURL=expo-standard-web-crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expo-standard-web-crypto.d.ts","sourceRoot":"","sources":["../../src/__mocks__/expo-standard-web-crypto.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAI7D;;;;AAGD,wBAEE"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Mock for expo-standard-web-crypto
|
|
4
|
+
* Uses Node.js crypto for getRandomValues in tests
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.getRandomValues = getRandomValues;
|
|
11
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
12
|
+
// Export getRandomValues directly for CommonJS compatibility
|
|
13
|
+
function getRandomValues(array) {
|
|
14
|
+
const randomBytes = crypto_1.default.randomBytes(array.length);
|
|
15
|
+
array.set(randomBytes);
|
|
16
|
+
return array;
|
|
17
|
+
}
|
|
18
|
+
// Also export as default for ESM compatibility
|
|
19
|
+
exports.default = {
|
|
20
|
+
getRandomValues,
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=expo-standard-web-crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expo-standard-web-crypto.js","sourceRoot":"","sources":["../../src/__mocks__/expo-standard-web-crypto.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;AAKH,0CAIC;AAPD,oDAA4B;AAE5B,6DAA6D;AAC7D,SAAgB,eAAe,CAAC,KAAiB;IAC/C,MAAM,WAAW,GAAG,gBAAM,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACrD,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACvB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,+CAA+C;AAC/C,kBAAe;IACb,eAAe;CAChB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ContentAddressedStoreFactory, CreateStoreResult, OpenStoreOptions } from "../core/types";
|
|
2
|
+
/**
|
|
3
|
+
* Factory for creating persistent on-disk content-addressed stores.
|
|
4
|
+
*/
|
|
5
|
+
export declare class BasicOnDiskContentAddressedStoreFactory implements ContentAddressedStoreFactory {
|
|
6
|
+
createStore(dbId: string, options?: OpenStoreOptions): CreateStoreResult;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=BasicOnDiskContentAddressedStoreFactory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BasicOnDiskContentAddressedStoreFactory.d.ts","sourceRoot":"","sources":["../../src/appendonlystores/BasicOnDiskContentAddressedStoreFactory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAElG;;GAEG;AACH,qBAAa,uCAAwC,YAAW,4BAA4B;IAC1F,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,iBAAiB;CAKzE"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BasicOnDiskContentAddressedStoreFactory = void 0;
|
|
4
|
+
const BasicOnDiskContentAddressedStore_1 = require("../node/appendonlystores/BasicOnDiskContentAddressedStore");
|
|
5
|
+
/**
|
|
6
|
+
* Factory for creating persistent on-disk content-addressed stores.
|
|
7
|
+
*/
|
|
8
|
+
class BasicOnDiskContentAddressedStoreFactory {
|
|
9
|
+
createStore(dbId, options) {
|
|
10
|
+
return {
|
|
11
|
+
docStore: new BasicOnDiskContentAddressedStore_1.BasicOnDiskContentAddressedStore(dbId, undefined, options),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.BasicOnDiskContentAddressedStoreFactory = BasicOnDiskContentAddressedStoreFactory;
|
|
16
|
+
//# sourceMappingURL=BasicOnDiskContentAddressedStoreFactory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BasicOnDiskContentAddressedStoreFactory.js","sourceRoot":"","sources":["../../src/appendonlystores/BasicOnDiskContentAddressedStoreFactory.ts"],"names":[],"mappings":";;;AAAA,gHAA6G;AAG7G;;GAEG;AACH,MAAa,uCAAuC;IAClD,WAAW,CAAC,IAAY,EAAE,OAA0B;QAClD,OAAO;YACL,QAAQ,EAAE,IAAI,mEAAgC,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC;SACzE,CAAC;IACJ,CAAC;CACF;AAND,0FAMC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ContentAddressedStoreFactory, CreateStoreResult, OpenStoreOptions } from "../core/types";
|
|
2
2
|
export declare class InMemoryContentAddressedStoreFactory implements ContentAddressedStoreFactory {
|
|
3
|
-
createStore(dbId: string,
|
|
3
|
+
createStore(dbId: string, options?: OpenStoreOptions): CreateStoreResult;
|
|
4
4
|
}
|
|
5
5
|
//# sourceMappingURL=InMemoryContentAddressedStoreFactory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InMemoryContentAddressedStoreFactory.d.ts","sourceRoot":"","sources":["../../src/appendonlystores/InMemoryContentAddressedStoreFactory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAElG,qBAAa,oCAAqC,YAAW,4BAA4B;IACvF,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"InMemoryContentAddressedStoreFactory.d.ts","sourceRoot":"","sources":["../../src/appendonlystores/InMemoryContentAddressedStoreFactory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAElG,qBAAa,oCAAqC,YAAW,4BAA4B;IACvF,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,iBAAiB;CASzE"}
|
|
@@ -3,12 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.InMemoryContentAddressedStoreFactory = void 0;
|
|
4
4
|
const InMemoryContentAddressedStore_1 = require("../core/appendonlystores/InMemoryContentAddressedStore");
|
|
5
5
|
class InMemoryContentAddressedStoreFactory {
|
|
6
|
-
createStore(dbId,
|
|
6
|
+
createStore(dbId, options) {
|
|
7
7
|
// For in-memory stores, we use a single store for both documents and attachments
|
|
8
8
|
// (no separate attachment store needed for simple/test scenarios)
|
|
9
9
|
// Note: options are ignored for in-memory stores but accepted for interface compatibility
|
|
10
10
|
return {
|
|
11
|
-
docStore: new InMemoryContentAddressedStore_1.InMemoryContentAddressedStore(dbId),
|
|
11
|
+
docStore: new InMemoryContentAddressedStore_1.InMemoryContentAddressedStore(dbId, undefined, options),
|
|
12
12
|
// attachmentStore not provided - will use docStore for attachments
|
|
13
13
|
};
|
|
14
14
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InMemoryContentAddressedStoreFactory.js","sourceRoot":"","sources":["../../src/appendonlystores/InMemoryContentAddressedStoreFactory.ts"],"names":[],"mappings":";;;AAAA,0GAAuG;AAGvG,MAAa,oCAAoC;IAC/C,WAAW,CAAC,IAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"InMemoryContentAddressedStoreFactory.js","sourceRoot":"","sources":["../../src/appendonlystores/InMemoryContentAddressedStoreFactory.ts"],"names":[],"mappings":";;;AAAA,0GAAuG;AAGvG,MAAa,oCAAoC;IAC/C,WAAW,CAAC,IAAY,EAAE,OAA0B;QAClD,iFAAiF;QACjF,kEAAkE;QAClE,0FAA0F;QAC1F,OAAO;YACL,QAAQ,EAAE,IAAI,6DAA6B,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC;YACrE,mEAAmE;SACpE,CAAC;IACJ,CAAC;CACF;AAVD,oFAUC"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { ContentAddressedStore } from "../../core/types";
|
|
2
|
-
import type { StoreEntry, StoreEntryMetadata } from "../../core/types";
|
|
2
|
+
import type { StoreEntry, StoreEntryMetadata, StoreEntryType, StoreScanCursor, StoreScanFilters, StoreScanResult, StoreIdBloomSummary, StoreCompactionStatus } from "../../core/types";
|
|
3
3
|
import type { CryptoAdapter } from "../../core/crypto/CryptoAdapter";
|
|
4
4
|
import type { NetworkTransport } from "../../core/appendonlystores/network/NetworkTransport";
|
|
5
|
+
import type { NetworkSyncCapabilities } from "../../core/appendonlystores/network/types";
|
|
6
|
+
import { Logger } from "../../core/logging";
|
|
5
7
|
/**
|
|
6
8
|
* Client-side network ContentAddressedStore that forwards all operations to a remote server.
|
|
7
9
|
*
|
|
@@ -26,6 +28,8 @@ export declare class ClientNetworkContentAddressedStore implements ContentAddres
|
|
|
26
28
|
private cryptoAdapter;
|
|
27
29
|
private accessToken;
|
|
28
30
|
private tokenExpiry;
|
|
31
|
+
private logger;
|
|
32
|
+
private capabilitiesCache;
|
|
29
33
|
/**
|
|
30
34
|
* Create a new ClientNetworkContentAddressedStore.
|
|
31
35
|
*
|
|
@@ -35,8 +39,9 @@ export declare class ClientNetworkContentAddressedStore implements ContentAddres
|
|
|
35
39
|
* @param username The username for authentication
|
|
36
40
|
* @param signingKey The user's private signing key (for signing challenges)
|
|
37
41
|
* @param privateEncryptionKey The user's private RSA key (for decrypting received entries)
|
|
42
|
+
* @param logger Optional logger instance
|
|
38
43
|
*/
|
|
39
|
-
constructor(dbId: string, transport: NetworkTransport, cryptoAdapter: CryptoAdapter, username: string, signingKey: CryptoKey, privateEncryptionKey: CryptoKey | string);
|
|
44
|
+
constructor(dbId: string, transport: NetworkTransport, cryptoAdapter: CryptoAdapter, username: string, signingKey: CryptoKey, privateEncryptionKey: CryptoKey | string, logger?: Logger);
|
|
40
45
|
getId(): string;
|
|
41
46
|
/**
|
|
42
47
|
* Store entries to the remote store.
|
|
@@ -68,11 +73,23 @@ export declare class ClientNetworkContentAddressedStore implements ContentAddres
|
|
|
68
73
|
* Find new entries for a specific document from the remote store.
|
|
69
74
|
*/
|
|
70
75
|
findNewEntriesForDoc(knownIds: string[], docId: string): Promise<StoreEntryMetadata[]>;
|
|
76
|
+
/**
|
|
77
|
+
* Find entries by type and creation date range from the remote store.
|
|
78
|
+
*/
|
|
79
|
+
findEntries(type: StoreEntryType, creationDateFrom: number | null, creationDateUntil: number | null): Promise<StoreEntryMetadata[]>;
|
|
71
80
|
/**
|
|
72
81
|
* Get all entry IDs from the remote store.
|
|
73
82
|
* Used for synchronization to identify which entries the remote has.
|
|
74
83
|
*/
|
|
75
84
|
getAllIds(): Promise<string[]>;
|
|
85
|
+
/**
|
|
86
|
+
* Cursor-based metadata scan from the remote store.
|
|
87
|
+
* Uses transport-native scan support when available, with a compatibility fallback.
|
|
88
|
+
*/
|
|
89
|
+
scanEntriesSince(cursor: StoreScanCursor | null, limit?: number, filters?: StoreScanFilters): Promise<StoreScanResult>;
|
|
90
|
+
getIdBloomSummary(): Promise<StoreIdBloomSummary>;
|
|
91
|
+
getCapabilities(): Promise<NetworkSyncCapabilities>;
|
|
92
|
+
getCompactionStatus(): Promise<StoreCompactionStatus>;
|
|
76
93
|
/**
|
|
77
94
|
* Resolve dependencies for an entry.
|
|
78
95
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientNetworkContentAddressedStore.d.ts","sourceRoot":"","sources":["../../../src/appendonlystores/network/ClientNetworkContentAddressedStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"ClientNetworkContentAddressedStore.d.ts","sourceRoot":"","sources":["../../../src/appendonlystores/network/ClientNetworkContentAddressedStore.ts"],"names":[],"mappings":"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"}
|