@mongrov/db 0.2.0
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 +332 -0
- package/dist/database.d.ts +42 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +83 -0
- package/dist/database.js.map +1 -0
- package/dist/hooks.d.ts +136 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +221 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/kv-backends/index.d.ts +6 -0
- package/dist/kv-backends/index.d.ts.map +1 -0
- package/dist/kv-backends/index.js +6 -0
- package/dist/kv-backends/index.js.map +1 -0
- package/dist/kv-backends/mmkv-backend.d.ts +21 -0
- package/dist/kv-backends/mmkv-backend.d.ts.map +1 -0
- package/dist/kv-backends/mmkv-backend.js +59 -0
- package/dist/kv-backends/mmkv-backend.js.map +1 -0
- package/dist/kv-backends/secure-backend.d.ts +27 -0
- package/dist/kv-backends/secure-backend.d.ts.map +1 -0
- package/dist/kv-backends/secure-backend.js +97 -0
- package/dist/kv-backends/secure-backend.js.map +1 -0
- package/dist/kv-store.d.ts +27 -0
- package/dist/kv-store.d.ts.map +1 -0
- package/dist/kv-store.js +34 -0
- package/dist/kv-store.js.map +1 -0
- package/dist/replication.d.ts +69 -0
- package/dist/replication.d.ts.map +1 -0
- package/dist/replication.js +147 -0
- package/dist/replication.js.map +1 -0
- package/dist/token-store.d.ts +38 -0
- package/dist/token-store.d.ts.map +1 -0
- package/dist/token-store.js +47 -0
- package/dist/token-store.js.map +1 -0
- package/dist/types.d.ts +175 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
package/README.md
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
# @mongrov/db
|
|
2
|
+
|
|
3
|
+
Database utilities for `@mongrov` apps:
|
|
4
|
+
|
|
5
|
+
- **KVStore** — Unified async key-value storage (MMKV + SecureStore)
|
|
6
|
+
- **RxDB** — Document database with reactive queries and offline-first support
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pnpm add @mongrov/db react-native-mmkv
|
|
12
|
+
|
|
13
|
+
# For secure storage (optional)
|
|
14
|
+
npx expo install expo-secure-store
|
|
15
|
+
|
|
16
|
+
# For RxDB document database (optional)
|
|
17
|
+
pnpm add rxdb rxdb-premium
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## KVStore
|
|
21
|
+
|
|
22
|
+
Unified async API over MMKV (fast) and SecureStore (secure).
|
|
23
|
+
|
|
24
|
+
### Basic Usage
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { createKVStore } from '@mongrov/db'
|
|
28
|
+
|
|
29
|
+
// Default MMKV store for preferences
|
|
30
|
+
const prefs = createKVStore()
|
|
31
|
+
await prefs.set('theme', 'dark')
|
|
32
|
+
const theme = await prefs.get('theme') // 'dark'
|
|
33
|
+
|
|
34
|
+
// Store objects (JSON serialized)
|
|
35
|
+
await prefs.setObject('user', { id: 1, name: 'Alice' })
|
|
36
|
+
const user = await prefs.getObject<User>('user')
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Secure Storage
|
|
40
|
+
|
|
41
|
+
Use for tokens, secrets, and sensitive data:
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
const tokens = createKVStore({ secure: true })
|
|
45
|
+
await tokens.set('accessToken', 'jwt...')
|
|
46
|
+
await tokens.set('refreshToken', 'refresh...')
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Instance Isolation
|
|
50
|
+
|
|
51
|
+
Create isolated stores with custom instance IDs:
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const cache = createKVStore({ instanceId: 'api-cache' })
|
|
55
|
+
const settings = createKVStore({ instanceId: 'user-settings' })
|
|
56
|
+
|
|
57
|
+
// These don't interfere with each other
|
|
58
|
+
await cache.set('data', 'cached')
|
|
59
|
+
await settings.set('data', 'settings')
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### API
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
interface KVStore {
|
|
66
|
+
// String operations
|
|
67
|
+
get(key: string): Promise<string | null>
|
|
68
|
+
set(key: string, value: string): Promise<void>
|
|
69
|
+
delete(key: string): Promise<void>
|
|
70
|
+
|
|
71
|
+
// Object operations (JSON serialization)
|
|
72
|
+
getObject<T>(key: string): Promise<T | null>
|
|
73
|
+
setObject<T>(key: string, value: T): Promise<void>
|
|
74
|
+
|
|
75
|
+
// Utility
|
|
76
|
+
clear(): Promise<void>
|
|
77
|
+
getAllKeys(): Promise<string[]>
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
interface KVStoreConfig {
|
|
81
|
+
secure?: boolean // Use SecureStore (default: false)
|
|
82
|
+
instanceId?: string // MMKV instance ID (default: 'mongrov-kv')
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Configuration Options
|
|
87
|
+
|
|
88
|
+
| Option | Default | Description |
|
|
89
|
+
|--------|---------|-------------|
|
|
90
|
+
| `secure` | `false` | Use expo-secure-store instead of MMKV |
|
|
91
|
+
| `instanceId` | `'mongrov-kv'` | MMKV instance ID for isolation (ignored when secure=true) |
|
|
92
|
+
|
|
93
|
+
## When to Use Each Backend
|
|
94
|
+
|
|
95
|
+
| Backend | Use For | Characteristics |
|
|
96
|
+
|---------|---------|-----------------|
|
|
97
|
+
| **MMKV** (default) | Preferences, theme, caches, flags | Fast, synchronous, large capacity |
|
|
98
|
+
| **SecureStore** | Tokens, secrets, credentials | Encrypted, platform keychain, 2KB limit per value |
|
|
99
|
+
|
|
100
|
+
## Auth Integration
|
|
101
|
+
|
|
102
|
+
Use `createTokenStore` to integrate with `@mongrov/auth`:
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { createKVStore, createTokenStore } from '@mongrov/db'
|
|
106
|
+
import { createAuthClient } from '@mongrov/auth'
|
|
107
|
+
|
|
108
|
+
// Create secure KVStore for tokens
|
|
109
|
+
const secureStore = createKVStore({ secure: true })
|
|
110
|
+
|
|
111
|
+
// Bridge to auth's TokenStore interface
|
|
112
|
+
const tokenStore = createTokenStore(secureStore)
|
|
113
|
+
|
|
114
|
+
// Use with auth client
|
|
115
|
+
const authClient = createAuthClient({
|
|
116
|
+
adapter: myAdapter,
|
|
117
|
+
tokenStore, // Tokens now stored via KVStore
|
|
118
|
+
})
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The `createTokenStore` function wraps a `KVStore` to implement auth's `TokenStore` interface:
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
interface TokenStore {
|
|
125
|
+
getAccessToken(): Promise<string | null>
|
|
126
|
+
setAccessToken(token: string): Promise<void>
|
|
127
|
+
getRefreshToken(): Promise<string | null>
|
|
128
|
+
setRefreshToken(token: string): Promise<void>
|
|
129
|
+
clear(): Promise<void>
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## RxDB Database
|
|
134
|
+
|
|
135
|
+
Create offline-first document databases with reactive queries.
|
|
136
|
+
|
|
137
|
+
### Creating a Database
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import { createDatabase } from '@mongrov/db'
|
|
141
|
+
import { getRxStorageSQLite } from 'rxdb-premium/plugins/storage-sqlite'
|
|
142
|
+
|
|
143
|
+
// Define your schema
|
|
144
|
+
const messageSchema = {
|
|
145
|
+
version: 0,
|
|
146
|
+
primaryKey: 'id',
|
|
147
|
+
type: 'object',
|
|
148
|
+
properties: {
|
|
149
|
+
id: { type: 'string', maxLength: 100 },
|
|
150
|
+
content: { type: 'string' },
|
|
151
|
+
conversationId: { type: 'string' },
|
|
152
|
+
createdAt: { type: 'number' },
|
|
153
|
+
},
|
|
154
|
+
required: ['id', 'content', 'conversationId'],
|
|
155
|
+
indexes: ['conversationId', 'createdAt'],
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Create the database
|
|
159
|
+
const db = await createDatabase({
|
|
160
|
+
name: 'myapp',
|
|
161
|
+
storage: getRxStorageSQLite(),
|
|
162
|
+
collections: [
|
|
163
|
+
{ name: 'messages', schema: messageSchema },
|
|
164
|
+
{ name: 'conversations', schema: conversationSchema },
|
|
165
|
+
],
|
|
166
|
+
logger: console, // Optional: log database operations
|
|
167
|
+
})
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### React Integration
|
|
171
|
+
|
|
172
|
+
Use the `DatabaseProvider` and hooks for reactive data access:
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
import {
|
|
176
|
+
DatabaseProvider,
|
|
177
|
+
useDatabase,
|
|
178
|
+
useCollection,
|
|
179
|
+
useQuery,
|
|
180
|
+
useDocument,
|
|
181
|
+
} from '@mongrov/db'
|
|
182
|
+
|
|
183
|
+
// Wrap your app with the provider
|
|
184
|
+
function App() {
|
|
185
|
+
const [db, setDb] = useState(null)
|
|
186
|
+
|
|
187
|
+
useEffect(() => {
|
|
188
|
+
createDatabase(config).then(setDb)
|
|
189
|
+
return () => db?.destroy()
|
|
190
|
+
}, [])
|
|
191
|
+
|
|
192
|
+
return (
|
|
193
|
+
<DatabaseProvider database={db}>
|
|
194
|
+
<MyApp />
|
|
195
|
+
</DatabaseProvider>
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Access database and collections
|
|
200
|
+
function MessageList({ conversationId }) {
|
|
201
|
+
const { db, isReady } = useDatabase()
|
|
202
|
+
const messages = useCollection('messages')
|
|
203
|
+
|
|
204
|
+
// Reactive query with automatic updates
|
|
205
|
+
const { data, isLoading, error } = useQuery('messages', {
|
|
206
|
+
selector: { conversationId },
|
|
207
|
+
sort: [{ createdAt: 'desc' }],
|
|
208
|
+
limit: 50,
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
if (isLoading) return <Loading />
|
|
212
|
+
if (error) return <Error message={error.message} />
|
|
213
|
+
|
|
214
|
+
return <FlatList data={data} renderItem={renderMessage} />
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Fetch single document by ID
|
|
218
|
+
function MessageDetail({ messageId }) {
|
|
219
|
+
const { data: message, isLoading } = useDocument('messages', messageId)
|
|
220
|
+
|
|
221
|
+
if (isLoading) return <Loading />
|
|
222
|
+
if (!message) return <NotFound />
|
|
223
|
+
|
|
224
|
+
return <MessageView message={message} />
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Schema Migrations
|
|
229
|
+
|
|
230
|
+
Handle schema upgrades with migration strategies:
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
const collections = [
|
|
234
|
+
{
|
|
235
|
+
name: 'messages',
|
|
236
|
+
schema: messageSchemaV2, // version: 2
|
|
237
|
+
migrationStrategies: {
|
|
238
|
+
1: (oldDoc) => ({ ...oldDoc, readStatus: 'unread' }),
|
|
239
|
+
2: (oldDoc) => ({ ...oldDoc, reactions: [] }),
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
]
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### API Reference
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
// Database factory
|
|
249
|
+
createDatabase(config: DatabaseConfig): Promise<RxDatabase>
|
|
250
|
+
destroyDatabase(db: RxDatabase): Promise<void>
|
|
251
|
+
|
|
252
|
+
// React hooks
|
|
253
|
+
useDatabase(): { db: RxDatabase | null, isReady: boolean }
|
|
254
|
+
useCollection<T>(name: string): RxCollection<T> | null
|
|
255
|
+
useQuery<T>(collection: string, query?: MangoQuery): QueryResult<T>
|
|
256
|
+
useDocument<T>(collection: string, id: string | null): DocumentResult<T>
|
|
257
|
+
|
|
258
|
+
// Result types
|
|
259
|
+
interface QueryResult<T> {
|
|
260
|
+
data: T[]
|
|
261
|
+
isLoading: boolean
|
|
262
|
+
error: Error | null
|
|
263
|
+
refetch: () => void
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
interface DocumentResult<T> {
|
|
267
|
+
data: T | null
|
|
268
|
+
isLoading: boolean
|
|
269
|
+
error: Error | null
|
|
270
|
+
refetch: () => void
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Replication
|
|
275
|
+
|
|
276
|
+
Sync collections with remote backends using push/pull handlers:
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
import { createReplicationState, cancelReplication } from '@mongrov/db'
|
|
280
|
+
|
|
281
|
+
// Create replication with push/pull handlers
|
|
282
|
+
const replication = createReplicationState({
|
|
283
|
+
replicationIdentifier: 'messages-sync',
|
|
284
|
+
collection: db.messages,
|
|
285
|
+
|
|
286
|
+
// Push local changes to remote
|
|
287
|
+
push: {
|
|
288
|
+
handler: async (docs) => {
|
|
289
|
+
await api.sendMessages(docs)
|
|
290
|
+
},
|
|
291
|
+
batchSize: 50,
|
|
292
|
+
},
|
|
293
|
+
|
|
294
|
+
// Pull remote changes
|
|
295
|
+
pull: {
|
|
296
|
+
handler: async (checkpoint, batchSize) => {
|
|
297
|
+
const result = await api.getMessages({ since: checkpoint, limit: batchSize })
|
|
298
|
+
return {
|
|
299
|
+
documents: result.messages,
|
|
300
|
+
checkpoint: result.lastTimestamp,
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
batchSize: 100,
|
|
304
|
+
},
|
|
305
|
+
|
|
306
|
+
live: true, // Enable real-time sync
|
|
307
|
+
logger: console,
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
// Listen for errors
|
|
311
|
+
replication.error$.subscribe((error) => {
|
|
312
|
+
console.error('Sync error:', error)
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
// Trigger manual sync
|
|
316
|
+
await replication.reSync()
|
|
317
|
+
|
|
318
|
+
// Stop replication when done
|
|
319
|
+
await cancelReplication(replication)
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
The replication helper is a thin wrapper over RxDB's replication plugin. Your push/pull handlers connect to your backend (REST API, WebSocket, or @mongrov/collab adapter).
|
|
323
|
+
|
|
324
|
+
## Peer Dependencies
|
|
325
|
+
|
|
326
|
+
- `react-native-mmkv` (required for KVStore)
|
|
327
|
+
- `expo-secure-store` (optional — only if using `secure: true`)
|
|
328
|
+
- `rxdb` (optional — only if using database features)
|
|
329
|
+
|
|
330
|
+
## License
|
|
331
|
+
|
|
332
|
+
MIT
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RxDB Database Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates a configured RxDB database instance with collections.
|
|
5
|
+
* App provides storage adapter (e.g., getRxStorageSQLite()).
|
|
6
|
+
*/
|
|
7
|
+
import type { DatabaseConfig, RxDatabaseType } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* Creates an RxDB database instance with configured collections.
|
|
10
|
+
*
|
|
11
|
+
* @param config - Database configuration
|
|
12
|
+
* @returns Promise resolving to the RxDB database instance
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { createDatabase } from '@mongrov/db'
|
|
17
|
+
* import { getRxStorageSQLite } from 'rxdb-premium/plugins/storage-sqlite'
|
|
18
|
+
*
|
|
19
|
+
* const db = await createDatabase({
|
|
20
|
+
* name: 'myapp',
|
|
21
|
+
* storage: getRxStorageSQLite(),
|
|
22
|
+
* collections: [
|
|
23
|
+
* {
|
|
24
|
+
* name: 'messages',
|
|
25
|
+
* schema: messageSchema,
|
|
26
|
+
* migrationStrategies: {
|
|
27
|
+
* 1: (oldDoc) => ({ ...oldDoc, newField: 'default' })
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
* ],
|
|
31
|
+
* logger: console,
|
|
32
|
+
* })
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function createDatabase(config: DatabaseConfig): Promise<RxDatabaseType>;
|
|
36
|
+
/**
|
|
37
|
+
* Destroys an RxDB database instance and cleans up resources.
|
|
38
|
+
*
|
|
39
|
+
* @param db - The database instance to destroy
|
|
40
|
+
*/
|
|
41
|
+
export declare function destroyDatabase(db: RxDatabaseType): Promise<void>;
|
|
42
|
+
//# sourceMappingURL=database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EAEf,MAAM,SAAS,CAAA;AAehB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAuCpF;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAIvE"}
|
package/dist/database.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RxDB Database Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates a configured RxDB database instance with collections.
|
|
5
|
+
* App provides storage adapter (e.g., getRxStorageSQLite()).
|
|
6
|
+
*/
|
|
7
|
+
import { createRxDatabase, addRxPlugin } from 'rxdb';
|
|
8
|
+
import { RxDBMigrationSchemaPlugin } from 'rxdb/plugins/migration-schema';
|
|
9
|
+
// Add migration plugin for schema upgrades
|
|
10
|
+
addRxPlugin(RxDBMigrationSchemaPlugin);
|
|
11
|
+
/**
|
|
12
|
+
* Default no-op logger for when none is provided.
|
|
13
|
+
*/
|
|
14
|
+
const noopLogger = {
|
|
15
|
+
debug: () => { },
|
|
16
|
+
info: () => { },
|
|
17
|
+
warn: () => { },
|
|
18
|
+
error: () => { },
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Creates an RxDB database instance with configured collections.
|
|
22
|
+
*
|
|
23
|
+
* @param config - Database configuration
|
|
24
|
+
* @returns Promise resolving to the RxDB database instance
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* import { createDatabase } from '@mongrov/db'
|
|
29
|
+
* import { getRxStorageSQLite } from 'rxdb-premium/plugins/storage-sqlite'
|
|
30
|
+
*
|
|
31
|
+
* const db = await createDatabase({
|
|
32
|
+
* name: 'myapp',
|
|
33
|
+
* storage: getRxStorageSQLite(),
|
|
34
|
+
* collections: [
|
|
35
|
+
* {
|
|
36
|
+
* name: 'messages',
|
|
37
|
+
* schema: messageSchema,
|
|
38
|
+
* migrationStrategies: {
|
|
39
|
+
* 1: (oldDoc) => ({ ...oldDoc, newField: 'default' })
|
|
40
|
+
* }
|
|
41
|
+
* }
|
|
42
|
+
* ],
|
|
43
|
+
* logger: console,
|
|
44
|
+
* })
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export async function createDatabase(config) {
|
|
48
|
+
const { name, storage, collections, logger = noopLogger, multiInstance = false, ignoreDuplicate = true, } = config;
|
|
49
|
+
logger.info('Creating database', { name, collectionCount: collections.length });
|
|
50
|
+
// Create the database
|
|
51
|
+
const db = await createRxDatabase({
|
|
52
|
+
name,
|
|
53
|
+
storage,
|
|
54
|
+
multiInstance,
|
|
55
|
+
ignoreDuplicate,
|
|
56
|
+
});
|
|
57
|
+
logger.debug('Database created', { name });
|
|
58
|
+
// Add collections
|
|
59
|
+
if (collections.length > 0) {
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
61
|
+
const collectionConfigs = {};
|
|
62
|
+
for (const col of collections) {
|
|
63
|
+
collectionConfigs[col.name] = {
|
|
64
|
+
schema: col.schema,
|
|
65
|
+
...(col.migrationStrategies && { migrationStrategies: col.migrationStrategies }),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
await db.addCollections(collectionConfigs);
|
|
69
|
+
logger.info('Collections added', { names: collections.map(c => c.name) });
|
|
70
|
+
}
|
|
71
|
+
return db;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Destroys an RxDB database instance and cleans up resources.
|
|
75
|
+
*
|
|
76
|
+
* @param db - The database instance to destroy
|
|
77
|
+
*/
|
|
78
|
+
export async function destroyDatabase(db) {
|
|
79
|
+
if (db && typeof db.destroy === 'function') {
|
|
80
|
+
await db.destroy();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,MAAM,CAAA;AACpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAA;AAQzE,2CAA2C;AAC3C,WAAW,CAAC,yBAAyB,CAAC,CAAA;AAEtC;;GAEG;AACH,MAAM,UAAU,GAAa;IAC3B,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;IACf,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;CAChB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAsB;IACzD,MAAM,EACJ,IAAI,EACJ,OAAO,EACP,WAAW,EACX,MAAM,GAAG,UAAU,EACnB,aAAa,GAAG,KAAK,EACrB,eAAe,GAAG,IAAI,GACvB,GAAG,MAAM,CAAA;IAEV,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,CAAA;IAE/E,sBAAsB;IACtB,MAAM,EAAE,GAAG,MAAM,gBAAgB,CAAC;QAChC,IAAI;QACJ,OAAO;QACP,aAAa;QACb,eAAe;KAChB,CAAC,CAAA;IAEF,MAAM,CAAC,KAAK,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;IAE1C,kBAAkB;IAClB,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,8DAA8D;QAC9D,MAAM,iBAAiB,GAAwB,EAAE,CAAA;QAEjD,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;YAC9B,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG;gBAC5B,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,GAAG,CAAC,GAAG,CAAC,mBAAmB,IAAI,EAAE,mBAAmB,EAAE,GAAG,CAAC,mBAAmB,EAAE,CAAC;aACjF,CAAA;QACH,CAAC;QAED,MAAM,EAAE,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAA;QAC1C,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC3E,CAAC;IAED,OAAO,EAAE,CAAA;AACX,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EAAkB;IACtD,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QAC3C,MAAM,EAAE,CAAC,OAAO,EAAE,CAAA;IACpB,CAAC;AACH,CAAC"}
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hooks for RxDB database access
|
|
3
|
+
*
|
|
4
|
+
* Provides context-based database injection and reactive query hooks.
|
|
5
|
+
*/
|
|
6
|
+
import { type ReactNode } from 'react';
|
|
7
|
+
import type { RxDatabaseType, RxCollectionType, RxDocumentType, MangoQueryType } from './types';
|
|
8
|
+
interface DatabaseContextValue {
|
|
9
|
+
db: RxDatabaseType | null;
|
|
10
|
+
isReady: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface DatabaseProviderProps {
|
|
13
|
+
/** The RxDB database instance (can be null during initialization) */
|
|
14
|
+
database: RxDatabaseType | null;
|
|
15
|
+
/** Child components */
|
|
16
|
+
children: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Provides database context to child components.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* function App() {
|
|
24
|
+
* const [db, setDb] = useState<RxDatabase | null>(null)
|
|
25
|
+
*
|
|
26
|
+
* useEffect(() => {
|
|
27
|
+
* createDatabase(config).then(setDb)
|
|
28
|
+
* }, [])
|
|
29
|
+
*
|
|
30
|
+
* return (
|
|
31
|
+
* <DatabaseProvider database={db}>
|
|
32
|
+
* <MyApp />
|
|
33
|
+
* </DatabaseProvider>
|
|
34
|
+
* )
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function DatabaseProvider({ database, children }: DatabaseProviderProps): ReactNode;
|
|
39
|
+
/**
|
|
40
|
+
* Hook to access the database context.
|
|
41
|
+
*
|
|
42
|
+
* @returns The database context value
|
|
43
|
+
* @throws If used outside of DatabaseProvider
|
|
44
|
+
*/
|
|
45
|
+
export declare function useDatabase(): DatabaseContextValue;
|
|
46
|
+
/**
|
|
47
|
+
* Hook to access a specific collection.
|
|
48
|
+
*
|
|
49
|
+
* @param name - Collection name
|
|
50
|
+
* @returns The collection instance or null if not ready
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```tsx
|
|
54
|
+
* function MessageList() {
|
|
55
|
+
* const messages = useCollection('messages')
|
|
56
|
+
*
|
|
57
|
+
* if (!messages) return <Loading />
|
|
58
|
+
*
|
|
59
|
+
* // Use messages collection...
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare function useCollection<T = RxCollectionType>(name: string): T | null;
|
|
64
|
+
/**
|
|
65
|
+
* Query result state.
|
|
66
|
+
*/
|
|
67
|
+
export interface QueryResult<T> {
|
|
68
|
+
/** The query results (empty array while loading) */
|
|
69
|
+
data: T[];
|
|
70
|
+
/** Whether the query is currently loading */
|
|
71
|
+
isLoading: boolean;
|
|
72
|
+
/** Error if the query failed */
|
|
73
|
+
error: Error | null;
|
|
74
|
+
/** Re-execute the query */
|
|
75
|
+
refetch: () => void;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Hook to execute a reactive query on a collection.
|
|
79
|
+
*
|
|
80
|
+
* @param collectionName - Name of the collection to query
|
|
81
|
+
* @param query - RxDB/Mango query selector
|
|
82
|
+
* @returns Query result with reactive updates
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```tsx
|
|
86
|
+
* function RecentMessages() {
|
|
87
|
+
* const { data, isLoading, error } = useQuery('messages', {
|
|
88
|
+
* selector: { createdAt: { $gt: Date.now() - 86400000 } },
|
|
89
|
+
* sort: [{ createdAt: 'desc' }],
|
|
90
|
+
* limit: 50,
|
|
91
|
+
* })
|
|
92
|
+
*
|
|
93
|
+
* if (isLoading) return <Loading />
|
|
94
|
+
* if (error) return <Error message={error.message} />
|
|
95
|
+
*
|
|
96
|
+
* return <MessageList messages={data} />
|
|
97
|
+
* }
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export declare function useQuery<T = RxDocumentType>(collectionName: string, query?: MangoQueryType): QueryResult<T>;
|
|
101
|
+
/**
|
|
102
|
+
* Document result state.
|
|
103
|
+
*/
|
|
104
|
+
export interface DocumentResult<T> {
|
|
105
|
+
/** The document data or null if not found */
|
|
106
|
+
data: T | null;
|
|
107
|
+
/** Whether the document is currently loading */
|
|
108
|
+
isLoading: boolean;
|
|
109
|
+
/** Error if the fetch failed */
|
|
110
|
+
error: Error | null;
|
|
111
|
+
/** Re-fetch the document */
|
|
112
|
+
refetch: () => void;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Hook to fetch and subscribe to a single document by ID.
|
|
116
|
+
*
|
|
117
|
+
* @param collectionName - Name of the collection
|
|
118
|
+
* @param id - Document primary key
|
|
119
|
+
* @returns Document result with reactive updates
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```tsx
|
|
123
|
+
* function MessageDetail({ messageId }: { messageId: string }) {
|
|
124
|
+
* const { data: message, isLoading, error } = useDocument('messages', messageId)
|
|
125
|
+
*
|
|
126
|
+
* if (isLoading) return <Loading />
|
|
127
|
+
* if (error) return <Error message={error.message} />
|
|
128
|
+
* if (!message) return <NotFound />
|
|
129
|
+
*
|
|
130
|
+
* return <MessageView message={message} />
|
|
131
|
+
* }
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
export declare function useDocument<T = RxDocumentType>(collectionName: string, id: string | null | undefined): DocumentResult<T>;
|
|
135
|
+
export {};
|
|
136
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AAEd,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,cAAc,EACf,MAAM,SAAS,CAAA;AAIhB,UAAU,oBAAoB;IAC5B,EAAE,EAAE,cAAc,GAAG,IAAI,CAAA;IACzB,OAAO,EAAE,OAAO,CAAA;CACjB;AAMD,MAAM,WAAW,qBAAqB;IACpC,qEAAqE;IACrE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAA;IAC/B,uBAAuB;IACvB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,qBAAqB,GAAG,SAAS,CAUzF;AAID;;;;;GAKG;AACH,wBAAgB,WAAW,IAAI,oBAAoB,CAmBlD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,CAAC,GAAG,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAQ1E;AAED;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,oDAAoD;IACpD,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,6CAA6C;IAC7C,SAAS,EAAE,OAAO,CAAA;IAClB,gCAAgC;IAChC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;IACnB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,GAAG,cAAc,EACzC,cAAc,EAAE,MAAM,EACtB,KAAK,GAAE,cAAmB,GACzB,WAAW,CAAC,CAAC,CAAC,CAuDhB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,6CAA6C;IAC7C,IAAI,EAAE,CAAC,GAAG,IAAI,CAAA;IACd,gDAAgD;IAChD,SAAS,EAAE,OAAO,CAAA;IAClB,gCAAgC;IAChC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;IACnB,4BAA4B;IAC5B,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,CAAC,GAAG,cAAc,EAC5C,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC5B,cAAc,CAAC,CAAC,CAAC,CAoDnB"}
|