mindoodb 0.0.2 → 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.
Files changed (172) hide show
  1. package/README.md +92 -19
  2. package/dist/__mocks__/expo-standard-web-crypto.d.ts +10 -0
  3. package/dist/__mocks__/expo-standard-web-crypto.d.ts.map +1 -0
  4. package/dist/__mocks__/expo-standard-web-crypto.js +22 -0
  5. package/dist/__mocks__/expo-standard-web-crypto.js.map +1 -0
  6. package/dist/appendonlystores/BasicOnDiskContentAddressedStoreFactory.d.ts +8 -0
  7. package/dist/appendonlystores/BasicOnDiskContentAddressedStoreFactory.d.ts.map +1 -0
  8. package/dist/appendonlystores/BasicOnDiskContentAddressedStoreFactory.js +16 -0
  9. package/dist/appendonlystores/BasicOnDiskContentAddressedStoreFactory.js.map +1 -0
  10. package/dist/appendonlystores/InMemoryContentAddressedStoreFactory.d.ts +1 -1
  11. package/dist/appendonlystores/InMemoryContentAddressedStoreFactory.d.ts.map +1 -1
  12. package/dist/appendonlystores/InMemoryContentAddressedStoreFactory.js +2 -2
  13. package/dist/appendonlystores/InMemoryContentAddressedStoreFactory.js.map +1 -1
  14. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.d.ts +11 -1
  15. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.d.ts.map +1 -1
  16. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js +94 -0
  17. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js.map +1 -1
  18. package/dist/appendonlystores/network/HttpTransport.d.ts +13 -2
  19. package/dist/appendonlystores/network/HttpTransport.d.ts.map +1 -1
  20. package/dist/appendonlystores/network/HttpTransport.js +86 -0
  21. package/dist/appendonlystores/network/HttpTransport.js.map +1 -1
  22. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts +19 -2
  23. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts.map +1 -1
  24. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.js +96 -0
  25. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.js.map +1 -1
  26. package/dist/appendonlystores/network/index.d.ts +1 -1
  27. package/dist/appendonlystores/network/index.d.ts.map +1 -1
  28. package/dist/appendonlystores/network/index.js.map +1 -1
  29. package/dist/browser/appendonlystores/IndexedDBContentAddressedStore.d.ts +61 -0
  30. package/dist/browser/appendonlystores/IndexedDBContentAddressedStore.d.ts.map +1 -0
  31. package/dist/browser/appendonlystores/IndexedDBContentAddressedStore.js +685 -0
  32. package/dist/browser/appendonlystores/IndexedDBContentAddressedStore.js.map +1 -0
  33. package/dist/browser/appendonlystores/IndexedDBContentAddressedStoreFactory.d.ts +25 -0
  34. package/dist/browser/appendonlystores/IndexedDBContentAddressedStoreFactory.d.ts.map +1 -0
  35. package/dist/browser/appendonlystores/IndexedDBContentAddressedStoreFactory.js +41 -0
  36. package/dist/browser/appendonlystores/IndexedDBContentAddressedStoreFactory.js.map +1 -0
  37. package/dist/browser/index.d.ts +5 -0
  38. package/dist/browser/index.d.ts.map +1 -1
  39. package/dist/browser/index.js +13 -1
  40. package/dist/browser/index.js.map +1 -1
  41. package/dist/core/BaseMindooDB.d.ts +12 -0
  42. package/dist/core/BaseMindooDB.d.ts.map +1 -1
  43. package/dist/core/BaseMindooDB.js +210 -108
  44. package/dist/core/BaseMindooDB.js.map +1 -1
  45. package/dist/core/BaseMindooTenant.d.ts +40 -6
  46. package/dist/core/BaseMindooTenant.d.ts.map +1 -1
  47. package/dist/core/BaseMindooTenant.js +179 -21
  48. package/dist/core/BaseMindooTenant.js.map +1 -1
  49. package/dist/core/BaseMindooTenantDirectory.d.ts.map +1 -1
  50. package/dist/core/BaseMindooTenantDirectory.js +10 -0
  51. package/dist/core/BaseMindooTenantDirectory.js.map +1 -1
  52. package/dist/core/BaseMindooTenantFactory.d.ts +22 -28
  53. package/dist/core/BaseMindooTenantFactory.d.ts.map +1 -1
  54. package/dist/core/BaseMindooTenantFactory.js +161 -65
  55. package/dist/core/BaseMindooTenantFactory.js.map +1 -1
  56. package/dist/core/appendonlystores/BasicOnDiskContentAddressedStore.d.ts +68 -0
  57. package/dist/core/appendonlystores/BasicOnDiskContentAddressedStore.d.ts.map +1 -0
  58. package/dist/core/appendonlystores/BasicOnDiskContentAddressedStore.js +659 -0
  59. package/dist/core/appendonlystores/BasicOnDiskContentAddressedStore.js.map +1 -0
  60. package/dist/core/appendonlystores/InMemoryContentAddressedStore.d.ts +43 -3
  61. package/dist/core/appendonlystores/InMemoryContentAddressedStore.d.ts.map +1 -1
  62. package/dist/core/appendonlystores/InMemoryContentAddressedStore.js +162 -23
  63. package/dist/core/appendonlystores/InMemoryContentAddressedStore.js.map +1 -1
  64. package/dist/core/appendonlystores/bloom.d.ts +85 -0
  65. package/dist/core/appendonlystores/bloom.d.ts.map +1 -0
  66. package/dist/core/appendonlystores/bloom.js +228 -0
  67. package/dist/core/appendonlystores/bloom.js.map +1 -0
  68. package/dist/core/appendonlystores/network/NetworkTransport.d.ts +22 -2
  69. package/dist/core/appendonlystores/network/NetworkTransport.d.ts.map +1 -1
  70. package/dist/core/appendonlystores/network/types.d.ts +10 -0
  71. package/dist/core/appendonlystores/network/types.d.ts.map +1 -1
  72. package/dist/core/appendonlystores/network/types.js.map +1 -1
  73. package/dist/core/appendonlystores/types.d.ts +123 -0
  74. package/dist/core/appendonlystores/types.d.ts.map +1 -1
  75. package/dist/core/automerge-adapter.d.ts +15 -0
  76. package/dist/core/automerge-adapter.d.ts.map +1 -0
  77. package/dist/core/automerge-adapter.js +73 -0
  78. package/dist/core/automerge-adapter.js.map +1 -0
  79. package/dist/core/crypto/pbkdf2Iterations.d.ts +12 -0
  80. package/dist/core/crypto/pbkdf2Iterations.d.ts.map +1 -0
  81. package/dist/core/crypto/pbkdf2Iterations.js +55 -0
  82. package/dist/core/crypto/pbkdf2Iterations.js.map +1 -0
  83. package/dist/core/index.d.ts +7 -2
  84. package/dist/core/index.d.ts.map +1 -1
  85. package/dist/core/index.js +30 -1
  86. package/dist/core/index.js.map +1 -1
  87. package/dist/core/keys/KeyBag.d.ts +32 -12
  88. package/dist/core/keys/KeyBag.d.ts.map +1 -1
  89. package/dist/core/keys/KeyBag.js +86 -26
  90. package/dist/core/keys/KeyBag.js.map +1 -1
  91. package/dist/core/keys/KeyContext.d.ts +4 -0
  92. package/dist/core/keys/KeyContext.d.ts.map +1 -0
  93. package/dist/core/keys/KeyContext.js +11 -0
  94. package/dist/core/keys/KeyContext.js.map +1 -0
  95. package/dist/core/types.d.ts +218 -50
  96. package/dist/core/types.d.ts.map +1 -1
  97. package/dist/core/types.js +2 -0
  98. package/dist/core/types.js.map +1 -1
  99. package/dist/core/uri/MindooURI.d.ts +58 -0
  100. package/dist/core/uri/MindooURI.d.ts.map +1 -0
  101. package/dist/core/uri/MindooURI.js +169 -0
  102. package/dist/core/uri/MindooURI.js.map +1 -0
  103. package/dist/core/userid/index.d.ts +0 -10
  104. package/dist/core/userid/index.d.ts.map +1 -1
  105. package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.d.ts +541 -0
  106. package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.d.ts.map +1 -0
  107. package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.js +1334 -0
  108. package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.js.map +1 -0
  109. package/dist/node/index.d.ts +1 -0
  110. package/dist/node/index.d.ts.map +1 -1
  111. package/dist/node/index.js +5 -1
  112. package/dist/node/index.js.map +1 -1
  113. package/dist/reactnative/crypto/AESAdapter.d.ts +18 -0
  114. package/dist/reactnative/crypto/AESAdapter.d.ts.map +1 -0
  115. package/dist/reactnative/crypto/AESAdapter.js +112 -0
  116. package/dist/reactnative/crypto/AESAdapter.js.map +1 -0
  117. package/dist/reactnative/crypto/Ed25519Adapter.d.ts +34 -0
  118. package/dist/reactnative/crypto/Ed25519Adapter.d.ts.map +1 -0
  119. package/dist/reactnative/crypto/Ed25519Adapter.js +386 -0
  120. package/dist/reactnative/crypto/Ed25519Adapter.js.map +1 -0
  121. package/dist/reactnative/crypto/ExpoGoCryptoAdapter.d.ts +23 -0
  122. package/dist/reactnative/crypto/ExpoGoCryptoAdapter.d.ts.map +1 -0
  123. package/dist/reactnative/crypto/ExpoGoCryptoAdapter.js +51 -0
  124. package/dist/reactnative/crypto/ExpoGoCryptoAdapter.js.map +1 -0
  125. package/dist/reactnative/crypto/HMACAdapter.d.ts +13 -0
  126. package/dist/reactnative/crypto/HMACAdapter.d.ts.map +1 -0
  127. package/dist/reactnative/crypto/HMACAdapter.js +50 -0
  128. package/dist/reactnative/crypto/HMACAdapter.js.map +1 -0
  129. package/dist/reactnative/crypto/KeyFormatConverter.d.ts +21 -0
  130. package/dist/reactnative/crypto/KeyFormatConverter.d.ts.map +1 -0
  131. package/dist/reactnative/crypto/KeyFormatConverter.js +72 -0
  132. package/dist/reactnative/crypto/KeyFormatConverter.js.map +1 -0
  133. package/dist/reactnative/crypto/PBKDF2Adapter.d.ts +19 -0
  134. package/dist/reactnative/crypto/PBKDF2Adapter.d.ts.map +1 -0
  135. package/dist/reactnative/crypto/PBKDF2Adapter.js +67 -0
  136. package/dist/reactnative/crypto/PBKDF2Adapter.js.map +1 -0
  137. package/dist/reactnative/crypto/QuickCryptoAdapter.d.ts +37 -0
  138. package/dist/reactnative/crypto/QuickCryptoAdapter.d.ts.map +1 -0
  139. package/dist/reactnative/crypto/QuickCryptoAdapter.js +72 -0
  140. package/dist/reactnative/crypto/QuickCryptoAdapter.js.map +1 -0
  141. package/dist/reactnative/crypto/RSAAdapter.d.ts +38 -0
  142. package/dist/reactnative/crypto/RSAAdapter.d.ts.map +1 -0
  143. package/dist/reactnative/crypto/RSAAdapter.js +184 -0
  144. package/dist/reactnative/crypto/RSAAdapter.js.map +1 -0
  145. package/dist/reactnative/crypto/ReactNativeCryptoAdapter.d.ts +33 -0
  146. package/dist/reactnative/crypto/ReactNativeCryptoAdapter.d.ts.map +1 -0
  147. package/dist/reactnative/crypto/ReactNativeCryptoAdapter.js +61 -0
  148. package/dist/reactnative/crypto/ReactNativeCryptoAdapter.js.map +1 -0
  149. package/dist/reactnative/crypto/SHA256Adapter.d.ts +9 -0
  150. package/dist/reactnative/crypto/SHA256Adapter.d.ts.map +1 -0
  151. package/dist/reactnative/crypto/SHA256Adapter.js +29 -0
  152. package/dist/reactnative/crypto/SHA256Adapter.js.map +1 -0
  153. package/dist/reactnative/crypto/SubtleCryptoPolyfill.d.ts +63 -0
  154. package/dist/reactnative/crypto/SubtleCryptoPolyfill.d.ts.map +1 -0
  155. package/dist/reactnative/crypto/SubtleCryptoPolyfill.js +350 -0
  156. package/dist/reactnative/crypto/SubtleCryptoPolyfill.js.map +1 -0
  157. package/dist/reactnative/index.d.ts +8 -0
  158. package/dist/reactnative/index.d.ts.map +1 -0
  159. package/dist/reactnative/index.js +38 -0
  160. package/dist/reactnative/index.js.map +1 -0
  161. package/package.json +51 -6
  162. package/patches/PATCHES.md +111 -0
  163. package/patches/react-native+0.76.9.patch +34 -0
  164. package/patches/react-native-quick-crypto+1.0.7.patch +42 -0
  165. package/scripts/cli.js +21 -0
  166. package/scripts/setup-react-native.js +228 -0
  167. package/templates/reactnative/App.js +252 -0
  168. package/templates/reactnative/app.json +29 -0
  169. package/templates/reactnative/babel.config.js +6 -0
  170. package/templates/reactnative/index.js +26 -0
  171. package/templates/reactnative/metro.config.snippet.js +39 -0
  172. package/templates/reactnative/mindoodb-polyfills.js +116 -0
@@ -0,0 +1,252 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { StatusBar } from 'expo-status-bar';
3
+ import {
4
+ StyleSheet,
5
+ Text,
6
+ View,
7
+ Button,
8
+ ScrollView,
9
+ ActivityIndicator,
10
+ Platform,
11
+ } from 'react-native';
12
+
13
+ // Lazy-load MindooDB to avoid blocking app registration
14
+ let BaseMindooTenantFactory, InMemoryContentAddressedStoreFactory, KeyBag, PUBLIC_INFOS_KEY_ID;
15
+ let QuickCryptoAdapter = null;
16
+ let ReactNativeCryptoAdapter = null;
17
+ let mindoodbLoaded = false;
18
+ let mindoodbLoadError = null;
19
+
20
+ function loadMindooDB() {
21
+ if (mindoodbLoaded) return;
22
+ try {
23
+ const mindoodb = require('mindoodb');
24
+ BaseMindooTenantFactory = mindoodb.BaseMindooTenantFactory;
25
+ InMemoryContentAddressedStoreFactory = mindoodb.InMemoryContentAddressedStoreFactory;
26
+ KeyBag = mindoodb.KeyBag;
27
+ PUBLIC_INFOS_KEY_ID = mindoodb.PUBLIC_INFOS_KEY_ID;
28
+ QuickCryptoAdapter = mindoodb.QuickCryptoAdapter;
29
+ ReactNativeCryptoAdapter = mindoodb.ReactNativeCryptoAdapter;
30
+ mindoodbLoaded = true;
31
+ } catch (error) {
32
+ mindoodbLoadError = error;
33
+ }
34
+ }
35
+
36
+ export default function App() {
37
+ const [testStatus, setTestStatus] = useState('idle');
38
+ const [testResults, setTestResults] = useState('');
39
+ const [isRunning, setIsRunning] = useState(false);
40
+
41
+ useEffect(() => {
42
+ if (!mindoodbLoaded && !mindoodbLoadError) loadMindooDB();
43
+ }, []);
44
+
45
+ const log = (msg) => setTestResults((prev) => prev + msg + '\n');
46
+
47
+ const runTest = async () => {
48
+ setIsRunning(true);
49
+ setTestStatus('running');
50
+ setTestResults('Starting test...\n');
51
+
52
+ try {
53
+ if (!mindoodbLoaded) throw new Error(mindoodbLoadError?.message || 'MindooDB not loaded');
54
+
55
+ // ── Step 1: Create store factory ──
56
+ log('Creating store factory...');
57
+ const storeFactory = new InMemoryContentAddressedStoreFactory();
58
+
59
+ // ── Step 2: Create crypto adapter ──
60
+ log(`Creating crypto adapter (${Platform.OS})...`);
61
+ const quickCrypto = require('react-native-quick-crypto');
62
+ const cryptoAdapter = new QuickCryptoAdapter(quickCrypto);
63
+ const subtle = cryptoAdapter.getSubtle();
64
+ log('Crypto adapter ready');
65
+
66
+ // ── Native crypto diagnostics ──
67
+ log('Running native crypto diagnostics...');
68
+ try {
69
+ const hash = quickCrypto.createHash('sha256');
70
+ hash.update('mindoodb-test');
71
+ hash.digest('hex');
72
+ log(' Hash.digest() works');
73
+ } catch (e) {
74
+ log(` Hash.digest() failed: ${e.message}`);
75
+ }
76
+ try {
77
+ await quickCrypto.subtle.digest('SHA-256', new Uint8Array([9, 8, 7, 6]));
78
+ log(' SubtleCrypto.digest() works');
79
+ } catch (e) {
80
+ log(` SubtleCrypto.digest() failed: ${e.message}`);
81
+ }
82
+ try {
83
+ quickCrypto.getRandomValues(new Uint8Array(8));
84
+ log(' getRandomValues() works');
85
+ } catch (e) {
86
+ log(` getRandomValues() failed: ${e.message}`);
87
+ }
88
+
89
+ // ── Step 3: Create tenant factory ──
90
+ log('Creating tenant factory...');
91
+ const factory = new BaseMindooTenantFactory(storeFactory, cryptoAdapter);
92
+
93
+ // ── Step 4: Create admin user + keys ──
94
+ log('Creating admin user...');
95
+ const adminUserPassword = 'adminpass123';
96
+ const adminUser = await factory.createUserId('CN=admin/O=testtenant', adminUserPassword);
97
+ log('Admin user created');
98
+
99
+ log('Creating key pairs...');
100
+ const adminSigningKeyPair = await factory.createSigningKeyPair('signingpass');
101
+ const adminEncryptionKeyPair = await factory.createEncryptionKeyPair('encpass');
102
+ const tenantEncryptionKey = await factory.createSymmetricEncryptedPrivateKey('tenantpass');
103
+ const publicInfosKey = await factory.createSymmetricEncryptedPrivateKey('publicinfospass');
104
+
105
+ log('Creating KeyBag...');
106
+ const adminKeyBag = new KeyBag(
107
+ adminUser.userEncryptionKeyPair.privateKey,
108
+ adminUserPassword,
109
+ cryptoAdapter
110
+ );
111
+ await adminKeyBag.decryptAndImportKey(PUBLIC_INFOS_KEY_ID, publicInfosKey, 'publicinfospass');
112
+
113
+ // ── Step 5: Open tenant ──
114
+ log('Opening tenant...');
115
+ const tenant = await factory.openTenantWithKeys(
116
+ 'test-tenant',
117
+ tenantEncryptionKey,
118
+ 'tenantpass',
119
+ adminSigningKeyPair.publicKey,
120
+ adminEncryptionKeyPair.publicKey,
121
+ adminUser,
122
+ adminUserPassword,
123
+ adminKeyBag
124
+ );
125
+
126
+ log('Registering admin user...');
127
+ const directory = await tenant.openDirectory();
128
+ await directory.registerUser(
129
+ factory.toPublicUserId(adminUser),
130
+ adminSigningKeyPair.privateKey,
131
+ 'signingpass'
132
+ );
133
+
134
+ // ── Step 6: Document test ──
135
+ log('\n=== Document Test ===');
136
+ const db = await tenant.openDB('test-db');
137
+ const numDocs = 10;
138
+ const createdDocs = [];
139
+ const baseTime = Date.now();
140
+
141
+ log(`Creating ${numDocs} documents...`);
142
+ for (let i = 0; i < numDocs; i++) {
143
+ const doc = await db.createDocument();
144
+ const docId = doc.getId();
145
+ await db.changeDoc(doc, (d) => {
146
+ const data = d.getData();
147
+ data.index = i;
148
+ data.timestamp = baseTime + i;
149
+ });
150
+ const updatedDoc = await db.getDocument(docId);
151
+ createdDocs.push({ docId, lastModified: updatedDoc.getLastModified() });
152
+ await new Promise((r) => setTimeout(r, 1));
153
+ }
154
+
155
+ await db.syncStoreChanges();
156
+
157
+ log('Iterating documents...');
158
+ const processedDocs = [];
159
+ for await (const { doc, cursor } of db.iterateChangesSince(null)) {
160
+ processedDocs.push({ docId: doc.getId(), lastModified: doc.getLastModified(), cursor });
161
+ }
162
+
163
+ // ── Verify ──
164
+ log('\n=== Results ===');
165
+ const allProcessed = processedDocs.length === numDocs;
166
+ log(`Documents: ${processedDocs.length}/${numDocs} ${allProcessed ? 'PASS' : 'FAIL'}`);
167
+
168
+ let orderCorrect = true;
169
+ for (let i = 1; i < processedDocs.length; i++) {
170
+ const prev = processedDocs[i - 1];
171
+ const curr = processedDocs[i];
172
+ if (prev.lastModified === curr.lastModified) {
173
+ if (prev.docId.localeCompare(curr.docId) > 0) { orderCorrect = false; break; }
174
+ } else if (prev.lastModified > curr.lastModified) { orderCorrect = false; break; }
175
+ }
176
+ log(`Order: ${orderCorrect ? 'PASS' : 'FAIL'}`);
177
+
178
+ let cursorCorrect = true;
179
+ for (const result of processedDocs) {
180
+ if (result.cursor.docId !== result.docId || result.cursor.lastModified !== result.lastModified) {
181
+ cursorCorrect = false;
182
+ break;
183
+ }
184
+ }
185
+ log(`Cursors: ${cursorCorrect ? 'PASS' : 'FAIL'}`);
186
+
187
+ if (allProcessed && orderCorrect && cursorCorrect) {
188
+ setTestStatus('success');
189
+ log('\n=== TEST PASSED ===');
190
+ console.log('=== TEST PASSED ===');
191
+ } else {
192
+ setTestStatus('error');
193
+ log('\n=== TEST FAILED ===');
194
+ console.error('=== TEST FAILED ===');
195
+ }
196
+ } catch (error) {
197
+ setTestStatus('error');
198
+ log(`\nERROR: ${error.message}\n${error.stack || ''}`);
199
+ console.error('Test error:', error);
200
+ } finally {
201
+ setIsRunning(false);
202
+ }
203
+ };
204
+
205
+ return (
206
+ <View style={styles.container}>
207
+ <StatusBar style="auto" />
208
+ <Text style={styles.title}>MindooDB Test App</Text>
209
+ <Text style={styles.subtitle}>React Native Integration Test</Text>
210
+
211
+ <View style={styles.buttonContainer}>
212
+ <Button
213
+ title={isRunning ? 'Running Test...' : 'Run Test (10 docs)'}
214
+ onPress={runTest}
215
+ disabled={isRunning}
216
+ color="#007AFF"
217
+ />
218
+ </View>
219
+
220
+ {isRunning && (
221
+ <View style={styles.loadingContainer}>
222
+ <ActivityIndicator size="large" color="#007AFF" />
223
+ <Text style={styles.loadingText}>Running test...</Text>
224
+ </View>
225
+ )}
226
+
227
+ {testStatus !== 'idle' && (
228
+ <View style={styles.resultsContainer}>
229
+ <Text style={styles.resultsTitle}>Test Results:</Text>
230
+ <ScrollView style={styles.resultsScroll}>
231
+ <Text style={styles.resultsText}>{testResults}</Text>
232
+ </ScrollView>
233
+ </View>
234
+ )}
235
+ </View>
236
+ );
237
+ }
238
+
239
+ const styles = StyleSheet.create({
240
+ container: { flex: 1, backgroundColor: '#fff', padding: 20, paddingTop: 60 },
241
+ title: { fontSize: 24, fontWeight: 'bold', marginBottom: 5, textAlign: 'center' },
242
+ subtitle: { fontSize: 16, color: '#666', textAlign: 'center', marginBottom: 30 },
243
+ buttonContainer: { marginBottom: 20 },
244
+ loadingContainer: { alignItems: 'center', marginVertical: 20 },
245
+ loadingText: { marginTop: 10, color: '#666' },
246
+ resultsContainer: {
247
+ flex: 1, borderWidth: 1, borderColor: '#ddd', borderRadius: 8, padding: 10, marginTop: 10,
248
+ },
249
+ resultsTitle: { fontSize: 18, fontWeight: 'bold', marginBottom: 10 },
250
+ resultsScroll: { flex: 1 },
251
+ resultsText: { fontSize: 12, fontFamily: 'monospace', color: '#333' },
252
+ });
@@ -0,0 +1,29 @@
1
+ {
2
+ "expo": {
3
+ "name": "my-mindoodb-app",
4
+ "slug": "my-mindoodb-app",
5
+ "version": "1.0.0",
6
+ "orientation": "portrait",
7
+ "icon": "./assets/splash-icon.png",
8
+ "userInterfaceStyle": "light",
9
+ "splash": {
10
+ "image": "./assets/splash-icon.png",
11
+ "resizeMode": "contain",
12
+ "backgroundColor": "#ffffff"
13
+ },
14
+ "assetBundlePatterns": ["**/*"],
15
+ "ios": {
16
+ "supportsTablet": true,
17
+ "bundleIdentifier": "com.example.myapp",
18
+ "jsEngine": "jsc"
19
+ },
20
+ "android": {
21
+ "adaptiveIcon": {
22
+ "foregroundImage": "./assets/adaptive-icon.png",
23
+ "backgroundColor": "#ffffff"
24
+ },
25
+ "package": "com.example.myapp"
26
+ },
27
+ "newArchEnabled": true
28
+ }
29
+ }
@@ -0,0 +1,6 @@
1
+ module.exports = function(api) {
2
+ api.cache(true);
3
+ return {
4
+ presets: ['babel-preset-expo'],
5
+ };
6
+ };
@@ -0,0 +1,26 @@
1
+ // MindooDB React Native Entry Point
2
+ //
3
+ // This file loads polyfills, initializes native Automerge via UseApi(nativeApi),
4
+ // then registers the app. Use this as a reference for your own index.js.
5
+
6
+ // Polyfills MUST be imported first (atob/btoa, crypto, TextDecoder, URL)
7
+ import './mindoodb-polyfills';
8
+
9
+ // Initialize native Automerge before registering the app
10
+ (async () => {
11
+ try {
12
+ const { UseApi } = require('@automerge/automerge/slim');
13
+ const { nativeApi } = require('react-native-automerge-generated');
14
+ UseApi(nativeApi);
15
+ console.log('Automerge native backend initialized');
16
+
17
+ // Register the app
18
+ const registerRootComponent = require('expo/src/launch/registerRootComponent').default;
19
+ const App = require('./App').default;
20
+ registerRootComponent(App);
21
+ } catch (error) {
22
+ console.error('MindooDB initialization failed:', error.message);
23
+ console.error(error.stack);
24
+ throw error;
25
+ }
26
+ })();
@@ -0,0 +1,39 @@
1
+ // ── MindooDB Metro Configuration ─────────────────────────────────────
2
+ //
3
+ // Add these settings to your metro.config.js.
4
+ // This snippet assumes you already have:
5
+ // const { getDefaultConfig } = require('expo/metro-config');
6
+ // const config = getDefaultConfig(__dirname);
7
+ //
8
+ // Paste the sections below BEFORE `module.exports = config;`
9
+
10
+ const path = require('path');
11
+
12
+ // Enable package exports for conditional imports (react-native, browser, node)
13
+ config.resolver.unstable_enablePackageExports = true;
14
+
15
+ // Prefer react-native field, then browser, then module, then main
16
+ config.resolver.resolverMainFields = ['react-native', 'browser', 'module', 'main'];
17
+
18
+ // Custom resolver: keep Automerge on the slim build for UseApi(nativeApi)
19
+ // and avoid accidental WASM/fullfat entrypoint usage.
20
+ const originalResolveRequest = config.resolver.resolveRequest;
21
+
22
+ config.resolver.resolveRequest = (context, moduleName, platform) => {
23
+ // Redirect @automerge/automerge and subpaths to slim.cjs
24
+ if (moduleName === '@automerge/automerge' || moduleName.startsWith('@automerge/automerge/')) {
25
+ const slim = path.resolve(
26
+ __dirname,
27
+ 'node_modules/@automerge/automerge/dist/cjs/slim.cjs'
28
+ );
29
+ if (require('fs').existsSync(slim)) {
30
+ return { filePath: slim, type: 'sourceFile' };
31
+ }
32
+ }
33
+
34
+ // Default resolution
35
+ if (originalResolveRequest) {
36
+ return originalResolveRequest(context, moduleName, platform);
37
+ }
38
+ return context.resolveRequest(context, moduleName, platform);
39
+ };
@@ -0,0 +1,116 @@
1
+ /**
2
+ * MindooDB Polyfills for React Native
3
+ *
4
+ * Import this file at the very top of your entry point (index.js),
5
+ * BEFORE any other imports:
6
+ *
7
+ * import "./mindoodb-polyfills";
8
+ *
9
+ * These polyfills are required because JavaScriptCore (JSC) on iOS
10
+ * does not provide atob/btoa, TextDecoder/TextEncoder, or the URL API.
11
+ * Automerge's base64-encoded WASM module needs atob to decode itself.
12
+ */
13
+
14
+ // ── atob / btoa ─────────────────────────────────────────────────────────
15
+ // JSC does not provide these. Required by Automerge's base64 WASM loader.
16
+
17
+ const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
18
+
19
+ function atobPolyfill(input) {
20
+ if (typeof input !== 'string') throw new TypeError('Expected string');
21
+ const str = input.replace(/[\s]/g, '');
22
+ if (str.length % 4 !== 0) throw new Error('Invalid base64 string');
23
+
24
+ let output = '';
25
+ for (let i = 0; i < str.length; i += 4) {
26
+ const a = base64Chars.indexOf(str.charAt(i));
27
+ const b = base64Chars.indexOf(str.charAt(i + 1));
28
+ const c = base64Chars.indexOf(str.charAt(i + 2));
29
+ const d = base64Chars.indexOf(str.charAt(i + 3));
30
+ if (a === -1 || b === -1 || c === -1 || d === -1) throw new Error('Invalid base64 character');
31
+ output += String.fromCharCode((a << 2) | (b >> 4));
32
+ if (c !== 64) output += String.fromCharCode(((b & 15) << 4) | (c >> 2));
33
+ if (d !== 64) output += String.fromCharCode(((c & 3) << 6) | d);
34
+ }
35
+ return output;
36
+ }
37
+
38
+ function btoaPolyfill(input) {
39
+ if (typeof input !== 'string') throw new TypeError('Expected string');
40
+ let output = '';
41
+ for (let i = 0; i < input.length; i += 3) {
42
+ const a = input.charCodeAt(i);
43
+ const b = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
44
+ const c = i + 2 < input.length ? input.charCodeAt(i + 2) : 0;
45
+ output += base64Chars.charAt(a >> 2);
46
+ output += base64Chars.charAt(((a & 3) << 4) | (b >> 4));
47
+ output += i + 1 < input.length ? base64Chars.charAt(((b & 15) << 2) | (c >> 6)) : '=';
48
+ output += i + 2 < input.length ? base64Chars.charAt(c & 63) : '=';
49
+ }
50
+ return output;
51
+ }
52
+
53
+ if (typeof global.atob === 'undefined') global.atob = atobPolyfill;
54
+ if (typeof global.btoa === 'undefined') global.btoa = btoaPolyfill;
55
+ if (typeof globalThis !== 'undefined') {
56
+ if (typeof globalThis.atob === 'undefined') globalThis.atob = atobPolyfill;
57
+ if (typeof globalThis.btoa === 'undefined') globalThis.btoa = btoaPolyfill;
58
+ }
59
+ if (typeof window !== 'undefined') {
60
+ if (typeof window.atob === 'undefined') window.atob = atobPolyfill;
61
+ if (typeof window.btoa === 'undefined') window.btoa = btoaPolyfill;
62
+ }
63
+
64
+ // ── Crypto ──────────────────────────────────────────────────────────────
65
+ // expo-standard-web-crypto provides getRandomValues; react-native-quick-crypto
66
+ // provides the full Web Crypto API (including subtle) via NitroModules.
67
+
68
+ import { polyfillWebCrypto } from 'expo-standard-web-crypto';
69
+
70
+ try {
71
+ const quickCrypto = require('react-native-quick-crypto');
72
+ if (typeof quickCrypto.install === 'function') {
73
+ quickCrypto.install();
74
+ }
75
+ } catch (_) {
76
+ // react-native-quick-crypto not available — MindooDB will fall back to JS crypto
77
+ }
78
+
79
+ if (typeof window !== 'undefined') {
80
+ polyfillWebCrypto();
81
+ }
82
+
83
+ // Ensure crypto is reachable on all global objects
84
+ if (typeof crypto !== 'undefined') {
85
+ if (typeof window !== 'undefined' && !window.crypto) window.crypto = crypto;
86
+ if (typeof global !== 'undefined' && !global.crypto) global.crypto = crypto;
87
+ if (typeof globalThis !== 'undefined' && !globalThis.crypto) globalThis.crypto = crypto;
88
+ }
89
+
90
+ // ── TextDecoder / TextEncoder ───────────────────────────────────────────
91
+ // Required before URL polyfill (whatwg-url needs TextDecoder).
92
+
93
+ try {
94
+ const textEncoding = require('text-encoding');
95
+ if (textEncoding.TextDecoder) {
96
+ global.TextDecoder = textEncoding.TextDecoder;
97
+ global.TextEncoder = textEncoding.TextEncoder;
98
+ if (typeof globalThis !== 'undefined') {
99
+ globalThis.TextDecoder = textEncoding.TextDecoder;
100
+ globalThis.TextEncoder = textEncoding.TextEncoder;
101
+ }
102
+ if (typeof window !== 'undefined') {
103
+ window.TextDecoder = textEncoding.TextDecoder;
104
+ window.TextEncoder = textEncoding.TextEncoder;
105
+ }
106
+ }
107
+ } catch (e) {
108
+ console.error('MindooDB: Failed to load text-encoding polyfill:', e.message);
109
+ }
110
+
111
+ // ── URL ─────────────────────────────────────────────────────────────────
112
+ try {
113
+ require('react-native-url-polyfill/auto');
114
+ } catch (_) {
115
+ // URL polyfill not available — may not be needed depending on usage
116
+ }