mindoodb 0.0.2 → 0.0.4
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-server.md +1001 -0
- package/README.md +89 -28
- 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 +30 -1
- package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.d.ts.map +1 -1
- package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js +152 -5
- package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js.map +1 -1
- package/dist/appendonlystores/network/HttpTransport.d.ts +17 -2
- package/dist/appendonlystores/network/HttpTransport.d.ts.map +1 -1
- package/dist/appendonlystores/network/HttpTransport.js +129 -0
- package/dist/appendonlystores/network/HttpTransport.js.map +1 -1
- package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts +22 -2
- package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts.map +1 -1
- package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.js +110 -0
- 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 +65 -0
- package/dist/browser/appendonlystores/IndexedDBContentAddressedStore.d.ts.map +1 -0
- package/dist/browser/appendonlystores/IndexedDBContentAddressedStore.js +741 -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/cache/IndexedDBLocalCacheStore.d.ts +21 -0
- package/dist/browser/cache/IndexedDBLocalCacheStore.d.ts.map +1 -0
- package/dist/browser/cache/IndexedDBLocalCacheStore.js +106 -0
- package/dist/browser/cache/IndexedDBLocalCacheStore.js.map +1 -0
- package/dist/browser/index.d.ts +8 -0
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +21 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/core/BaseMindooDB.d.ts +115 -13
- package/dist/core/BaseMindooDB.d.ts.map +1 -1
- package/dist/core/BaseMindooDB.js +1232 -269
- package/dist/core/BaseMindooDB.js.map +1 -1
- package/dist/core/BaseMindooTenant.d.ts +69 -6
- package/dist/core/BaseMindooTenant.d.ts.map +1 -1
- package/dist/core/BaseMindooTenant.js +302 -109
- package/dist/core/BaseMindooTenant.js.map +1 -1
- package/dist/core/BaseMindooTenantDirectory.d.ts +13 -10
- package/dist/core/BaseMindooTenantDirectory.d.ts.map +1 -1
- package/dist/core/BaseMindooTenantDirectory.js +144 -27
- package/dist/core/BaseMindooTenantDirectory.js.map +1 -1
- package/dist/core/BaseMindooTenantFactory.d.ts +27 -29
- package/dist/core/BaseMindooTenantFactory.d.ts.map +1 -1
- package/dist/core/BaseMindooTenantFactory.js +185 -112
- package/dist/core/BaseMindooTenantFactory.js.map +1 -1
- package/dist/core/MindooDBServerAdmin.d.ts +238 -0
- package/dist/core/MindooDBServerAdmin.d.ts.map +1 -0
- package/dist/core/MindooDBServerAdmin.js +345 -0
- package/dist/core/MindooDBServerAdmin.js.map +1 -0
- 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 +45 -3
- package/dist/core/appendonlystores/InMemoryContentAddressedStore.d.ts.map +1 -1
- package/dist/core/appendonlystores/InMemoryContentAddressedStore.js +184 -23
- package/dist/core/appendonlystores/InMemoryContentAddressedStore.js.map +1 -1
- package/dist/core/appendonlystores/MaterializationPlanner.d.ts +49 -0
- package/dist/core/appendonlystores/MaterializationPlanner.d.ts.map +1 -0
- package/dist/core/appendonlystores/MaterializationPlanner.js +325 -0
- package/dist/core/appendonlystores/MaterializationPlanner.js.map +1 -0
- 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/NetworkTransport.d.ts +37 -2
- package/dist/core/appendonlystores/network/NetworkTransport.d.ts.map +1 -1
- package/dist/core/appendonlystores/network/types.d.ts +12 -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 +206 -0
- 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/cache/CacheManager.d.ts +75 -0
- package/dist/core/cache/CacheManager.d.ts.map +1 -0
- package/dist/core/cache/CacheManager.js +101 -0
- package/dist/core/cache/CacheManager.js.map +1 -0
- package/dist/core/cache/EncryptedLocalCacheStore.d.ts +41 -0
- package/dist/core/cache/EncryptedLocalCacheStore.d.ts.map +1 -0
- package/dist/core/cache/EncryptedLocalCacheStore.js +120 -0
- package/dist/core/cache/EncryptedLocalCacheStore.js.map +1 -0
- package/dist/core/cache/LocalCacheStore.d.ts +50 -0
- package/dist/core/cache/LocalCacheStore.d.ts.map +1 -0
- package/dist/core/cache/LocalCacheStore.js +39 -0
- package/dist/core/cache/LocalCacheStore.js.map +1 -0
- 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/crypto/privateKeyEncryption.d.ts +5 -0
- package/dist/core/crypto/privateKeyEncryption.d.ts.map +1 -0
- package/dist/core/crypto/privateKeyEncryption.js +87 -0
- package/dist/core/crypto/privateKeyEncryption.js.map +1 -0
- package/dist/core/index.d.ts +18 -6
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +42 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/indexing/virtualviews/MindooDBVirtualViewDataProvider.d.ts +4 -1
- package/dist/core/indexing/virtualviews/MindooDBVirtualViewDataProvider.d.ts.map +1 -1
- package/dist/core/indexing/virtualviews/MindooDBVirtualViewDataProvider.js +39 -11
- package/dist/core/indexing/virtualviews/MindooDBVirtualViewDataProvider.js.map +1 -1
- package/dist/core/indexing/virtualviews/ViewEntrySortKeyComparator.d.ts +1 -0
- package/dist/core/indexing/virtualviews/ViewEntrySortKeyComparator.d.ts.map +1 -1
- package/dist/core/indexing/virtualviews/ViewEntrySortKeyComparator.js +3 -0
- package/dist/core/indexing/virtualviews/ViewEntrySortKeyComparator.js.map +1 -1
- package/dist/core/indexing/virtualviews/VirtualView.d.ts +43 -0
- package/dist/core/indexing/virtualviews/VirtualView.d.ts.map +1 -1
- package/dist/core/indexing/virtualviews/VirtualView.js +173 -0
- package/dist/core/indexing/virtualviews/VirtualView.js.map +1 -1
- package/dist/core/indexing/virtualviews/VirtualViewEntryData.d.ts +7 -0
- package/dist/core/indexing/virtualviews/VirtualViewEntryData.d.ts.map +1 -1
- package/dist/core/indexing/virtualviews/VirtualViewEntryData.js +28 -0
- package/dist/core/indexing/virtualviews/VirtualViewEntryData.js.map +1 -1
- package/dist/core/keys/KeyBag.d.ts +56 -12
- package/dist/core/keys/KeyBag.d.ts.map +1 -1
- package/dist/core/keys/KeyBag.js +156 -70
- 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 +17 -0
- package/dist/core/keys/KeyContext.js.map +1 -0
- package/dist/core/types.d.ts +512 -60
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +9 -1
- 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/core/utils/idGeneration.d.ts.map +1 -1
- package/dist/core/utils/idGeneration.js +37 -3
- package/dist/core/utils/idGeneration.js.map +1 -1
- package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.d.ts +544 -0
- package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.d.ts.map +1 -0
- package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.js +1358 -0
- package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.js.map +1 -0
- package/dist/node/attachments/writeAttachmentToFile.d.ts +15 -0
- package/dist/node/attachments/writeAttachmentToFile.d.ts.map +1 -0
- package/dist/node/attachments/writeAttachmentToFile.js +73 -0
- package/dist/node/attachments/writeAttachmentToFile.js.map +1 -0
- package/dist/node/cache/FileSystemLocalCacheStore.d.ts +17 -0
- package/dist/node/cache/FileSystemLocalCacheStore.d.ts.map +1 -0
- package/dist/node/cache/FileSystemLocalCacheStore.js +128 -0
- package/dist/node/cache/FileSystemLocalCacheStore.js.map +1 -0
- package/dist/node/cli/change-identity-password.d.ts +7 -0
- package/dist/node/cli/change-identity-password.d.ts.map +1 -0
- package/dist/node/cli/change-identity-password.js +67 -0
- package/dist/node/cli/change-identity-password.js.map +1 -0
- package/dist/node/cli/cli-utils.d.ts +16 -0
- package/dist/node/cli/cli-utils.d.ts.map +1 -0
- package/dist/node/cli/cli-utils.js +113 -0
- package/dist/node/cli/cli-utils.js.map +1 -0
- package/dist/node/cli/identity-export-public.d.ts +4 -0
- package/dist/node/cli/identity-export-public.d.ts.map +1 -0
- package/dist/node/cli/identity-export-public.js +55 -0
- package/dist/node/cli/identity-export-public.js.map +1 -0
- package/dist/node/cli/identity-info.d.ts +4 -0
- package/dist/node/cli/identity-info.d.ts.map +1 -0
- package/dist/node/cli/identity-info.js +57 -0
- package/dist/node/cli/identity-info.js.map +1 -0
- package/dist/node/index.d.ts +2 -0
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +8 -1
- package/dist/node/index.js.map +1 -1
- package/dist/node/server/CapabilityMatcher.d.ts +45 -0
- package/dist/node/server/CapabilityMatcher.d.ts.map +1 -0
- package/dist/node/server/CapabilityMatcher.js +117 -0
- package/dist/node/server/CapabilityMatcher.js.map +1 -0
- package/dist/node/server/MindooDBServer.d.ts +87 -0
- package/dist/node/server/MindooDBServer.d.ts.map +1 -0
- package/dist/node/server/MindooDBServer.js +1040 -0
- package/dist/node/server/MindooDBServer.js.map +1 -0
- package/dist/node/server/ServerSync.d.ts +41 -0
- package/dist/node/server/ServerSync.d.ts.map +1 -0
- package/dist/node/server/ServerSync.js +187 -0
- package/dist/node/server/ServerSync.js.map +1 -0
- package/dist/node/server/StoreFactory.d.ts +45 -0
- package/dist/node/server/StoreFactory.d.ts.map +1 -0
- package/dist/node/server/StoreFactory.js +89 -0
- package/dist/node/server/StoreFactory.js.map +1 -0
- package/dist/node/server/SystemAdminAuth.d.ts +65 -0
- package/dist/node/server/SystemAdminAuth.d.ts.map +1 -0
- package/dist/node/server/SystemAdminAuth.js +200 -0
- package/dist/node/server/SystemAdminAuth.js.map +1 -0
- package/dist/node/server/SystemIpAllowlist.d.ts +21 -0
- package/dist/node/server/SystemIpAllowlist.d.ts.map +1 -0
- package/dist/node/server/SystemIpAllowlist.js +210 -0
- package/dist/node/server/SystemIpAllowlist.js.map +1 -0
- package/dist/node/server/TenantManager.d.ts +85 -0
- package/dist/node/server/TenantManager.d.ts.map +1 -0
- package/dist/node/server/TenantManager.js +493 -0
- package/dist/node/server/TenantManager.js.map +1 -0
- package/dist/node/server/add-to-network.d.ts +20 -0
- package/dist/node/server/add-to-network.d.ts.map +1 -0
- package/dist/node/server/add-to-network.js +275 -0
- package/dist/node/server/add-to-network.js.map +1 -0
- package/dist/node/server/config.d.ts +51 -0
- package/dist/node/server/config.d.ts.map +1 -0
- package/dist/node/server/config.js +218 -0
- package/dist/node/server/config.js.map +1 -0
- package/dist/node/server/resolveServerPassword.d.ts +7 -0
- package/dist/node/server/resolveServerPassword.d.ts.map +1 -0
- package/dist/node/server/resolveServerPassword.js +25 -0
- package/dist/node/server/resolveServerPassword.js.map +1 -0
- package/dist/node/server/server.d.ts +22 -0
- package/dist/node/server/server.d.ts.map +1 -0
- package/dist/node/server/server.js +225 -0
- package/dist/node/server/server.js.map +1 -0
- package/dist/node/server/serverinit.d.ts +21 -0
- package/dist/node/server/serverinit.d.ts.map +1 -0
- package/dist/node/server/serverinit.js +317 -0
- package/dist/node/server/serverinit.js.map +1 -0
- package/dist/node/server/types.d.ts +162 -0
- package/dist/node/server/types.d.ts.map +1 -0
- package/dist/node/server/types.js +24 -0
- package/dist/node/server/types.js.map +1 -0
- package/dist/node/server/validation.d.ts +47 -0
- package/dist/node/server/validation.d.ts.map +1 -0
- package/dist/node/server/validation.js +114 -0
- package/dist/node/server/validation.js.map +1 -0
- package/dist/reactnative/cache/MMKVLocalCacheStore.d.ts +48 -0
- package/dist/reactnative/cache/MMKVLocalCacheStore.d.ts.map +1 -0
- package/dist/reactnative/cache/MMKVLocalCacheStore.js +113 -0
- package/dist/reactnative/cache/MMKVLocalCacheStore.js.map +1 -0
- 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 +9 -0
- package/dist/reactnative/index.d.ts.map +1 -0
- package/dist/reactnative/index.js +41 -0
- package/dist/reactnative/index.js.map +1 -0
- package/package.json +63 -7
- 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
|
@@ -11,6 +11,9 @@ Your data is encrypted on the client before it ever touches a server. No plainte
|
|
|
11
11
|
|
|
12
12
|
> ⚠️ **Alpha software**: This project is in early development and not yet recommended for production use. APIs may change without notice.
|
|
13
13
|
|
|
14
|
+
Use AI to explore this repository:
|
|
15
|
+
|
|
16
|
+
[](https://deepwiki.com/klehmann/MindooDB)
|
|
14
17
|
|
|
15
18
|
## The Problem
|
|
16
19
|
|
|
@@ -44,7 +47,7 @@ Traditional databases trust the server. If your hosting provider is compromised,
|
|
|
44
47
|
└──────────────────────────────────────────────────────────────────┘
|
|
45
48
|
```
|
|
46
49
|
|
|
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.
|
|
50
|
+
**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
51
|
|
|
49
52
|
## Key Features
|
|
50
53
|
|
|
@@ -65,37 +68,43 @@ Traditional databases trust the server. If your hosting provider is compromised,
|
|
|
65
68
|
npm install mindoodb
|
|
66
69
|
```
|
|
67
70
|
|
|
71
|
+
> 📱 **React Native / Expo?** See the [React Native setup guide](./docs/reactnative.md) for mobile-specific instructions with native performance.
|
|
72
|
+
|
|
73
|
+
### Pick Your Runtime
|
|
74
|
+
|
|
75
|
+
| Runtime | Fastest start | Recommended path |
|
|
76
|
+
|---------|---------------|------------------|
|
|
77
|
+
| Node.js | Use `mindoodb` directly in a Node script | [Getting Started](./docs/getting-started.md#nodejs) |
|
|
78
|
+
| Web | Import from `mindoodb/browser` | [Getting Started](./docs/getting-started.md#web-browser) |
|
|
79
|
+
| React Native / Expo | Run `npx mindoodb setup-react-native` in your app root | [React Native Guide](./docs/reactnative.md) |
|
|
80
|
+
|
|
81
|
+
### React Native Recommendation
|
|
82
|
+
|
|
83
|
+
- Use **native Automerge** (`react-native-automerge-generated`) and native crypto for production.
|
|
84
|
+
- Treat Expo Go / JS fallback as a convenience path for prototyping, not the default production runtime.
|
|
85
|
+
|
|
68
86
|
### Create a Tenant and Start Working
|
|
69
87
|
|
|
70
88
|
```typescript
|
|
71
89
|
import {
|
|
72
90
|
BaseMindooTenantFactory,
|
|
73
|
-
|
|
74
|
-
KeyBag
|
|
91
|
+
InMemoryContentAddressedStoreFactory,
|
|
75
92
|
} from "mindoodb";
|
|
76
93
|
|
|
77
94
|
// 1. Set up storage (in-memory for demo; use file/server-backed for production)
|
|
78
|
-
const storeFactory = new
|
|
95
|
+
const storeFactory = new InMemoryContentAddressedStoreFactory();
|
|
79
96
|
const factory = new BaseMindooTenantFactory(storeFactory);
|
|
80
97
|
|
|
81
|
-
// 2. Create
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const tenant = await factory.createTenant(
|
|
90
|
-
"acme-corp",
|
|
91
|
-
adminKeyPair.publicKey,
|
|
92
|
-
"tenant-key-password",
|
|
93
|
-
user,
|
|
94
|
-
"user-password",
|
|
95
|
-
keyBag
|
|
96
|
-
);
|
|
98
|
+
// 2. Create tenant (generates all keys, opens tenant, registers user — single call)
|
|
99
|
+
const { tenant, adminUser, appUser, keyBag } = await factory.createTenant({
|
|
100
|
+
tenantId: "acme-corp",
|
|
101
|
+
adminName: "cn=admin/o=acme",
|
|
102
|
+
adminPassword: "admin-password",
|
|
103
|
+
userName: "cn=alice/o=acme",
|
|
104
|
+
userPassword: "user-password",
|
|
105
|
+
});
|
|
97
106
|
|
|
98
|
-
//
|
|
107
|
+
// 3. Open a database and create documents
|
|
99
108
|
const db = await tenant.openDB("contacts");
|
|
100
109
|
const doc = await db.createDocument();
|
|
101
110
|
|
|
@@ -105,7 +114,7 @@ await db.changeDoc(doc, async (d) => {
|
|
|
105
114
|
data.email = "john@example.com";
|
|
106
115
|
});
|
|
107
116
|
|
|
108
|
-
//
|
|
117
|
+
// 4. Read it back
|
|
109
118
|
const contacts = await db.getAllDocumentIds();
|
|
110
119
|
const loaded = await db.getDocument(contacts[0]);
|
|
111
120
|
console.log(loaded.getData()); // { name: "John Doe", email: "john@example.com" }
|
|
@@ -200,20 +209,20 @@ All encryption keys are stored in the **KeyBag**—a local, password-protected k
|
|
|
200
209
|
| **`default` key** | Used when no other key is specified | All tenant members |
|
|
201
210
|
| **Named keys** | Fine-grained access for sensitive docs | Only users you share it with |
|
|
202
211
|
|
|
203
|
-
Keys are distributed offline (email
|
|
212
|
+
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.
|
|
204
213
|
|
|
205
214
|
## Security
|
|
206
215
|
|
|
207
216
|
### Cryptographic Guarantees
|
|
208
|
-
- **Signatures**: Ed25519 on every change
|
|
209
|
-
- **Encryption**: AES-256-GCM
|
|
210
|
-
- **Integrity**: Changes are hash-chained
|
|
217
|
+
- **Signatures**: Ed25519 on every change - proves who wrote it
|
|
218
|
+
- **Encryption**: AES-256-GCM - servers see only ciphertext
|
|
219
|
+
- **Integrity**: Changes are hash-chained - tampering breaks the chain
|
|
211
220
|
|
|
212
221
|
### User Revocation
|
|
213
222
|
Revoked users:
|
|
214
223
|
- ❌ Cannot sync with peers or servers
|
|
215
224
|
- ❌ Cannot make new changes (signatures rejected)
|
|
216
|
-
- ⚠️ Can
|
|
225
|
+
- ⚠️ Can currently read previously-synced local data (planned: data wipe on first connect after revocation)
|
|
217
226
|
|
|
218
227
|
MindooDB includes **revocation timestamp protection** to prevent backdated changes from revoked users. See: [Revocation Protection](./docs/revocation-timestamp-protection.md)
|
|
219
228
|
|
|
@@ -223,6 +232,13 @@ Append-only storage means nothing is ever deleted:
|
|
|
223
232
|
- Cryptographic proof of all operations
|
|
224
233
|
- GDPR compliance via `purgeDocHistory()` when legally required
|
|
225
234
|
|
|
235
|
+
## Supported Platforms
|
|
236
|
+
|
|
237
|
+
- ✅ **Node.js** - Server-side and desktop apps
|
|
238
|
+
- ✅ **Web Browsers** - Progressive web apps with Web Crypto API
|
|
239
|
+
- ✅ **React Native / Expo** - iOS and Android with native Automerge (Rust via JSI)
|
|
240
|
+
- ✅ **Electron** - Cross-platform desktop apps
|
|
241
|
+
|
|
226
242
|
## Use Cases
|
|
227
243
|
|
|
228
244
|
- **Multi-Tenant SaaS**: Each customer isolated with encrypted data
|
|
@@ -230,21 +246,66 @@ Append-only storage means nothing is ever deleted:
|
|
|
230
246
|
- **Secure File Sharing**: Named keys for need-to-know access
|
|
231
247
|
- **Audit-Critical Systems**: Tamperproof history meets compliance requirements
|
|
232
248
|
- **Offline-First Apps**: Full functionality without network; sync when connected
|
|
249
|
+
- **Mobile Apps**: End-to-end encrypted sync with native performance
|
|
233
250
|
|
|
234
251
|
See: [Use Cases Documentation](./docs/usecases/README.md)
|
|
235
252
|
|
|
236
253
|
## Documentation
|
|
237
254
|
|
|
255
|
+
- [Getting Started](./docs/getting-started.md) — Fast setup for Node.js, Web, and React Native
|
|
256
|
+
- [Example Snippets](./docs/examples/README.md) — Copy-paste Todo starters for all runtimes
|
|
238
257
|
- [Architecture Specification](./docs/specification.md) — Full technical details
|
|
258
|
+
- [React Native Guide](./docs/reactnative.md) — Native Automerge setup and troubleshooting
|
|
239
259
|
- [Virtual Views](./docs/virtualview.md) — Aggregations and cross-database views
|
|
240
260
|
- [Data Indexing](./docs/dataindexing.md) — Incremental indexing and search integration
|
|
241
261
|
- [Time Travel](./docs/timetravel.md) — Historical document retrieval and history traversal
|
|
242
262
|
- [P2P Sync](./docs/p2psync.md) — Peer-to-peer synchronization
|
|
243
263
|
- [Attachments](./docs/attachments.md) — File storage and streaming
|
|
244
264
|
|
|
265
|
+
## Testing
|
|
266
|
+
|
|
267
|
+
Run tests from the command line:
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
# Node.js unit/integration tests (Jest)
|
|
271
|
+
npm test
|
|
272
|
+
|
|
273
|
+
# Install Chromium once for browser tests
|
|
274
|
+
npm run test:browser:install
|
|
275
|
+
|
|
276
|
+
# Real browser runtime tests (Playwright + headless Chromium)
|
|
277
|
+
npm run test:browser
|
|
278
|
+
|
|
279
|
+
# Run Node + browser lanes
|
|
280
|
+
npm run test:all
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Test coverage by environment
|
|
284
|
+
|
|
285
|
+
| Environment | Command | What is covered today |
|
|
286
|
+
|-------------|---------|------------------------|
|
|
287
|
+
| Node.js | `npm test` | Full Jest suite for core APIs (documents, sync logic, indexing, virtual views, settings, trust model, attachments, etc.) |
|
|
288
|
+
| 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 |
|
|
289
|
+
| 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 |
|
|
290
|
+
|
|
291
|
+
### Browser sync test behavior
|
|
292
|
+
|
|
293
|
+
- Browser tests run in headless Chromium and execute MindooDB browser code in a real page runtime.
|
|
294
|
+
- During test setup, an ephemeral HTTP server is started automatically and exposes the real sync endpoints.
|
|
295
|
+
- Sync assertions use real HTTP requests against that temporary endpoint (no mocked transport for sync tests).
|
|
296
|
+
- The server binds to an OS-assigned free port and is shut down after the suite completes.
|
|
297
|
+
|
|
298
|
+
### Current parity status
|
|
299
|
+
|
|
300
|
+
- The package exports and core API shape are aligned across Node.js, browser, and React Native entrypoints.
|
|
301
|
+
- Node and browser now have executable CLI lanes with runtime validation.
|
|
302
|
+
- React Native coverage is currently adapter-focused in Jest and does not yet validate full app-level behavior inside a real React Native runtime.
|
|
303
|
+
- 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.
|
|
304
|
+
- For Expo Go / JS fallback scenarios, PBKDF2 iterations can be tuned at runtime; native RN builds should keep strong defaults.
|
|
305
|
+
|
|
245
306
|
## Support
|
|
246
307
|
|
|
247
|
-
Need
|
|
308
|
+
Need commercial support, have questions, or want to request a feature? We're here to help! :-)
|
|
248
309
|
|
|
249
310
|
- 🐛 **Bug Reports**: [Open an issue on GitHub](https://github.com/klehmann/mindoodb/issues)
|
|
250
311
|
- 💬 **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, StoreEntryType } from "../../core/types";
|
|
2
|
+
import type { StoreEntry, StoreEntryMetadata, StoreEntryType, StoreScanCursor, StoreScanFilters, StoreScanResult, StoreIdBloomSummary, StoreCompactionStatus } from "../../core/types";
|
|
3
|
+
import type { DocumentMaterializationBatchPlan, DocumentMaterializationPlan, MaterializationPlanOptions } from "../../core/appendonlystores/types";
|
|
3
4
|
import type { CryptoAdapter } from "../../core/crypto/CryptoAdapter";
|
|
4
5
|
import type { NetworkTransport } from "../../core/appendonlystores/network/NetworkTransport";
|
|
6
|
+
import type { NetworkSyncCapabilities } from "../../core/appendonlystores/network/types";
|
|
5
7
|
import { Logger } from "../../core/logging";
|
|
6
8
|
/**
|
|
7
9
|
* Client-side network ContentAddressedStore that forwards all operations to a remote server.
|
|
@@ -28,6 +30,8 @@ export declare class ClientNetworkContentAddressedStore implements ContentAddres
|
|
|
28
30
|
private accessToken;
|
|
29
31
|
private tokenExpiry;
|
|
30
32
|
private logger;
|
|
33
|
+
private capabilitiesCache;
|
|
34
|
+
private syncAuthOverride;
|
|
31
35
|
/**
|
|
32
36
|
* Create a new ClientNetworkContentAddressedStore.
|
|
33
37
|
*
|
|
@@ -41,6 +45,7 @@ export declare class ClientNetworkContentAddressedStore implements ContentAddres
|
|
|
41
45
|
*/
|
|
42
46
|
constructor(dbId: string, transport: NetworkTransport, cryptoAdapter: CryptoAdapter, username: string, signingKey: CryptoKey, privateEncryptionKey: CryptoKey | string, logger?: Logger);
|
|
43
47
|
getId(): string;
|
|
48
|
+
getCacheIdentity(): string;
|
|
44
49
|
/**
|
|
45
50
|
* Store entries to the remote store.
|
|
46
51
|
* The entries are pushed to the server immediately.
|
|
@@ -80,6 +85,16 @@ export declare class ClientNetworkContentAddressedStore implements ContentAddres
|
|
|
80
85
|
* Used for synchronization to identify which entries the remote has.
|
|
81
86
|
*/
|
|
82
87
|
getAllIds(): Promise<string[]>;
|
|
88
|
+
/**
|
|
89
|
+
* Cursor-based metadata scan from the remote store.
|
|
90
|
+
* Uses transport-native scan support when available, with a compatibility fallback.
|
|
91
|
+
*/
|
|
92
|
+
scanEntriesSince(cursor: StoreScanCursor | null, limit?: number, filters?: StoreScanFilters): Promise<StoreScanResult>;
|
|
93
|
+
getIdBloomSummary(): Promise<StoreIdBloomSummary>;
|
|
94
|
+
getCapabilities(): Promise<NetworkSyncCapabilities>;
|
|
95
|
+
getCompactionStatus(): Promise<StoreCompactionStatus>;
|
|
96
|
+
planDocumentMaterialization(docId: string, options?: MaterializationPlanOptions): Promise<DocumentMaterializationPlan>;
|
|
97
|
+
planDocumentMaterializationBatch(docIds: string[], options?: MaterializationPlanOptions): Promise<DocumentMaterializationBatchPlan>;
|
|
83
98
|
/**
|
|
84
99
|
* Resolve dependencies for an entry.
|
|
85
100
|
*
|
|
@@ -104,6 +119,7 @@ export declare class ClientNetworkContentAddressedStore implements ContentAddres
|
|
|
104
119
|
* Sign a challenge with the user's private signing key.
|
|
105
120
|
*/
|
|
106
121
|
private signChallenge;
|
|
122
|
+
private signChallengeWithKey;
|
|
107
123
|
/**
|
|
108
124
|
* Decrypt network-encrypted entries.
|
|
109
125
|
* Transforms NetworkEncryptedEntry[] to StoreEntry[].
|
|
@@ -114,5 +130,18 @@ export declare class ClientNetworkContentAddressedStore implements ContentAddres
|
|
|
114
130
|
* Call this if you need to force re-authentication.
|
|
115
131
|
*/
|
|
116
132
|
clearAuthCache(): void;
|
|
133
|
+
/**
|
|
134
|
+
* Set or clear a temporary per-sync authentication override.
|
|
135
|
+
* Intended for bootstrap scenarios (for example authenticating as admin).
|
|
136
|
+
*/
|
|
137
|
+
setSyncAuthOverride(override: {
|
|
138
|
+
username: string;
|
|
139
|
+
signingKey: CryptoKey;
|
|
140
|
+
privateEncryptionKey?: CryptoKey | string;
|
|
141
|
+
} | null): void;
|
|
142
|
+
clearSyncAuthOverride(): void;
|
|
143
|
+
private getActiveAuthUsername;
|
|
144
|
+
private getActiveSigningKey;
|
|
145
|
+
private getActivePrivateEncryptionKey;
|
|
117
146
|
}
|
|
118
147
|
//# sourceMappingURL=ClientNetworkContentAddressedStore.d.ts.map
|
|
@@ -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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"}
|
|
@@ -4,6 +4,7 @@ exports.ClientNetworkContentAddressedStore = void 0;
|
|
|
4
4
|
const types_1 = require("../../core/appendonlystores/network/types");
|
|
5
5
|
const RSAEncryption_1 = require("../../core/crypto/RSAEncryption");
|
|
6
6
|
const logging_1 = require("../../core/logging");
|
|
7
|
+
const bloom_1 = require("../../core/appendonlystores/bloom");
|
|
7
8
|
/**
|
|
8
9
|
* Client-side network ContentAddressedStore that forwards all operations to a remote server.
|
|
9
10
|
*
|
|
@@ -34,6 +35,8 @@ class ClientNetworkContentAddressedStore {
|
|
|
34
35
|
// Cached access token
|
|
35
36
|
this.accessToken = null;
|
|
36
37
|
this.tokenExpiry = 0;
|
|
38
|
+
this.capabilitiesCache = null;
|
|
39
|
+
this.syncAuthOverride = null;
|
|
37
40
|
this.dbId = dbId;
|
|
38
41
|
this.transport = transport;
|
|
39
42
|
this.cryptoAdapter = cryptoAdapter;
|
|
@@ -49,6 +52,10 @@ class ClientNetworkContentAddressedStore {
|
|
|
49
52
|
getId() {
|
|
50
53
|
return this.dbId;
|
|
51
54
|
}
|
|
55
|
+
getCacheIdentity() {
|
|
56
|
+
const transportId = this.transport.getIdentity?.() ?? "unknown";
|
|
57
|
+
return `net:${transportId}/${this.dbId}`;
|
|
58
|
+
}
|
|
52
59
|
/**
|
|
53
60
|
* Store entries to the remote store.
|
|
54
61
|
* The entries are pushed to the server immediately.
|
|
@@ -142,6 +149,115 @@ class ClientNetworkContentAddressedStore {
|
|
|
142
149
|
this.logger.debug(`Remote has ${allIds.length} entry IDs`);
|
|
143
150
|
return allIds;
|
|
144
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Cursor-based metadata scan from the remote store.
|
|
154
|
+
* Uses transport-native scan support when available, with a compatibility fallback.
|
|
155
|
+
*/
|
|
156
|
+
async scanEntriesSince(cursor, limit = Number.MAX_SAFE_INTEGER, filters) {
|
|
157
|
+
const token = await this.ensureAuthenticated();
|
|
158
|
+
const capabilities = await this.getCapabilities();
|
|
159
|
+
if (capabilities.supportsCursorScan && this.transport.scanEntriesSince) {
|
|
160
|
+
return this.transport.scanEntriesSince(token, cursor, limit, filters);
|
|
161
|
+
}
|
|
162
|
+
// Compatibility fallback: fetch metadata via legacy endpoint and paginate client-side.
|
|
163
|
+
const all = await this.findNewEntries([]);
|
|
164
|
+
const filtered = all
|
|
165
|
+
.filter((meta) => {
|
|
166
|
+
if (filters?.docId && meta.docId !== filters.docId) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
if (filters?.entryTypes && filters.entryTypes.length > 0 && !filters.entryTypes.includes(meta.entryType)) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
if (filters?.creationDateFrom !== undefined && filters.creationDateFrom !== null && meta.createdAt < filters.creationDateFrom) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
if (filters?.creationDateUntil !== undefined && filters.creationDateUntil !== null && meta.createdAt >= filters.creationDateUntil) {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
return true;
|
|
179
|
+
})
|
|
180
|
+
.sort((a, b) => (a.createdAt === b.createdAt ? a.id.localeCompare(b.id) : a.createdAt - b.createdAt));
|
|
181
|
+
const startIndex = cursor === null
|
|
182
|
+
? 0
|
|
183
|
+
: filtered.findIndex((meta) => meta.createdAt > cursor.createdAt || (meta.createdAt === cursor.createdAt && meta.id > cursor.id));
|
|
184
|
+
if (startIndex === -1) {
|
|
185
|
+
return { entries: [], nextCursor: cursor, hasMore: false };
|
|
186
|
+
}
|
|
187
|
+
const page = filtered.slice(startIndex, startIndex + limit);
|
|
188
|
+
const last = page.length > 0 ? page[page.length - 1] : null;
|
|
189
|
+
return {
|
|
190
|
+
entries: page,
|
|
191
|
+
nextCursor: last ? { createdAt: last.createdAt, id: last.id } : cursor,
|
|
192
|
+
hasMore: startIndex + page.length < filtered.length,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
async getIdBloomSummary() {
|
|
196
|
+
const token = await this.ensureAuthenticated();
|
|
197
|
+
const capabilities = await this.getCapabilities();
|
|
198
|
+
if (capabilities.supportsIdBloomSummary && this.transport.getIdBloomSummary) {
|
|
199
|
+
return this.transport.getIdBloomSummary(token);
|
|
200
|
+
}
|
|
201
|
+
// Compatibility fallback for older transports.
|
|
202
|
+
const ids = await this.getAllIds();
|
|
203
|
+
return (0, bloom_1.createIdBloomSummary)(ids);
|
|
204
|
+
}
|
|
205
|
+
async getCapabilities() {
|
|
206
|
+
if (this.capabilitiesCache) {
|
|
207
|
+
return this.capabilitiesCache;
|
|
208
|
+
}
|
|
209
|
+
const token = await this.ensureAuthenticated();
|
|
210
|
+
if (this.transport.getCapabilities) {
|
|
211
|
+
this.capabilitiesCache = await this.transport.getCapabilities(token);
|
|
212
|
+
return this.capabilitiesCache;
|
|
213
|
+
}
|
|
214
|
+
this.capabilitiesCache = {
|
|
215
|
+
protocolVersion: "sync-v1",
|
|
216
|
+
supportsCursorScan: false,
|
|
217
|
+
supportsIdBloomSummary: false,
|
|
218
|
+
supportsCompactionStatus: false,
|
|
219
|
+
supportsMaterializationPlanning: false,
|
|
220
|
+
supportsBatchMaterializationPlanning: false,
|
|
221
|
+
};
|
|
222
|
+
return this.capabilitiesCache;
|
|
223
|
+
}
|
|
224
|
+
async getCompactionStatus() {
|
|
225
|
+
const token = await this.ensureAuthenticated();
|
|
226
|
+
const capabilities = await this.getCapabilities();
|
|
227
|
+
if (capabilities.supportsCompactionStatus && this.transport.getCompactionStatus) {
|
|
228
|
+
return this.transport.getCompactionStatus(token);
|
|
229
|
+
}
|
|
230
|
+
// Compatibility fallback for older transports.
|
|
231
|
+
return {
|
|
232
|
+
enabled: false,
|
|
233
|
+
compactionMinFiles: 0,
|
|
234
|
+
compactionMaxBytes: 0,
|
|
235
|
+
totalCompactions: 0,
|
|
236
|
+
totalCompactedFiles: 0,
|
|
237
|
+
totalCompactedBytes: 0,
|
|
238
|
+
totalCompactionDurationMs: 0,
|
|
239
|
+
lastCompactionAt: null,
|
|
240
|
+
lastCompactedFiles: 0,
|
|
241
|
+
lastCompactedBytes: 0,
|
|
242
|
+
lastCompactionDurationMs: 0,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
async planDocumentMaterialization(docId, options) {
|
|
246
|
+
const token = await this.ensureAuthenticated();
|
|
247
|
+
const capabilities = await this.getCapabilities();
|
|
248
|
+
if (!capabilities.supportsMaterializationPlanning || !this.transport.planDocumentMaterialization) {
|
|
249
|
+
throw new Error("Remote server does not support required materialization planning protocol");
|
|
250
|
+
}
|
|
251
|
+
return this.transport.planDocumentMaterialization(token, docId, options);
|
|
252
|
+
}
|
|
253
|
+
async planDocumentMaterializationBatch(docIds, options) {
|
|
254
|
+
const token = await this.ensureAuthenticated();
|
|
255
|
+
const capabilities = await this.getCapabilities();
|
|
256
|
+
if (!capabilities.supportsBatchMaterializationPlanning || !this.transport.planDocumentMaterializationBatch) {
|
|
257
|
+
throw new Error("Remote server does not support required batch materialization planning protocol");
|
|
258
|
+
}
|
|
259
|
+
return this.transport.planDocumentMaterializationBatch(token, docIds, options);
|
|
260
|
+
}
|
|
145
261
|
/**
|
|
146
262
|
* Resolve dependencies for an entry.
|
|
147
263
|
*
|
|
@@ -176,12 +292,13 @@ class ClientNetworkContentAddressedStore {
|
|
|
176
292
|
if (this.accessToken && this.tokenExpiry > now + 60000) { // 1 minute buffer
|
|
177
293
|
return this.accessToken;
|
|
178
294
|
}
|
|
179
|
-
|
|
295
|
+
const authUsername = this.getActiveAuthUsername();
|
|
296
|
+
this.logger.debug(`Authenticating user: ${authUsername}`);
|
|
180
297
|
// Request a challenge
|
|
181
|
-
const challenge = await this.transport.requestChallenge(
|
|
298
|
+
const challenge = await this.transport.requestChallenge(authUsername);
|
|
182
299
|
this.logger.debug(`Received challenge: ${challenge}`);
|
|
183
300
|
// Sign the challenge
|
|
184
|
-
const signature = await this.
|
|
301
|
+
const signature = await this.signChallengeWithKey(challenge, this.getActiveSigningKey());
|
|
185
302
|
this.logger.debug(`Signed challenge`);
|
|
186
303
|
// Authenticate
|
|
187
304
|
const result = await this.transport.authenticate(challenge, signature);
|
|
@@ -208,9 +325,12 @@ class ClientNetworkContentAddressedStore {
|
|
|
208
325
|
* Sign a challenge with the user's private signing key.
|
|
209
326
|
*/
|
|
210
327
|
async signChallenge(challenge) {
|
|
328
|
+
return this.signChallengeWithKey(challenge, this.signingKey);
|
|
329
|
+
}
|
|
330
|
+
async signChallengeWithKey(challenge, signingKey) {
|
|
211
331
|
const subtle = this.cryptoAdapter.getSubtle();
|
|
212
332
|
const messageBytes = new TextEncoder().encode(challenge);
|
|
213
|
-
const signature = await subtle.sign({ name: "Ed25519" },
|
|
333
|
+
const signature = await subtle.sign({ name: "Ed25519" }, signingKey, messageBytes);
|
|
214
334
|
return new Uint8Array(signature);
|
|
215
335
|
}
|
|
216
336
|
/**
|
|
@@ -221,7 +341,7 @@ class ClientNetworkContentAddressedStore {
|
|
|
221
341
|
const results = [];
|
|
222
342
|
for (const enc of encryptedEntries) {
|
|
223
343
|
// Decrypt the RSA layer to get the original symmetric-encrypted payload
|
|
224
|
-
const encryptedData = await this.rsaEncryption.decrypt(enc.rsaEncryptedPayload, this.
|
|
344
|
+
const encryptedData = await this.rsaEncryption.decrypt(enc.rsaEncryptedPayload, this.getActivePrivateEncryptionKey());
|
|
225
345
|
// Create the full StoreEntry using metadata from the network entry
|
|
226
346
|
const entry = {
|
|
227
347
|
entryType: enc.entryType,
|
|
@@ -232,6 +352,8 @@ class ClientNetworkContentAddressedStore {
|
|
|
232
352
|
createdAt: enc.createdAt,
|
|
233
353
|
createdByPublicKey: enc.createdByPublicKey,
|
|
234
354
|
decryptionKeyId: enc.decryptionKeyId,
|
|
355
|
+
snapshotHeadHashes: enc.snapshotHeadHashes,
|
|
356
|
+
snapshotHeadEntryIds: enc.snapshotHeadEntryIds,
|
|
235
357
|
signature: enc.signature,
|
|
236
358
|
originalSize: enc.originalSize,
|
|
237
359
|
encryptedSize: enc.encryptedSize,
|
|
@@ -248,6 +370,31 @@ class ClientNetworkContentAddressedStore {
|
|
|
248
370
|
clearAuthCache() {
|
|
249
371
|
this.accessToken = null;
|
|
250
372
|
this.tokenExpiry = 0;
|
|
373
|
+
this.capabilitiesCache = null;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Set or clear a temporary per-sync authentication override.
|
|
377
|
+
* Intended for bootstrap scenarios (for example authenticating as admin).
|
|
378
|
+
*/
|
|
379
|
+
setSyncAuthOverride(override) {
|
|
380
|
+
this.syncAuthOverride = override;
|
|
381
|
+
// Changing auth identity requires token refresh.
|
|
382
|
+
this.clearAuthCache();
|
|
383
|
+
}
|
|
384
|
+
clearSyncAuthOverride() {
|
|
385
|
+
if (this.syncAuthOverride) {
|
|
386
|
+
this.syncAuthOverride = null;
|
|
387
|
+
this.clearAuthCache();
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
getActiveAuthUsername() {
|
|
391
|
+
return this.syncAuthOverride?.username ?? this.username;
|
|
392
|
+
}
|
|
393
|
+
getActiveSigningKey() {
|
|
394
|
+
return this.syncAuthOverride?.signingKey ?? this.signingKey;
|
|
395
|
+
}
|
|
396
|
+
getActivePrivateEncryptionKey() {
|
|
397
|
+
return this.syncAuthOverride?.privateEncryptionKey ?? this.privateEncryptionKey;
|
|
251
398
|
}
|
|
252
399
|
}
|
|
253
400
|
exports.ClientNetworkContentAddressedStore = ClientNetworkContentAddressedStore;
|