@rivium/sync-node 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Rivium
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,440 @@
1
+ # @rivium/sync-node
2
+
3
+ Official Node.js SDK for RiviumSync Realtime Database. Designed for server-side applications with admin-level access.
4
+
5
+ ## Features
6
+
7
+ - **Admin-level access** - Bypasses security rules by default
8
+ - **Full CRUD operations** - Create, read, update, delete documents
9
+ - **Query support** - Filters, sorting, pagination
10
+ - **Batch operations** - Atomic writes across multiple documents
11
+ - **Optional realtime** - MQTT-based subscriptions when needed
12
+ - **TypeScript** - Full type definitions included
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ # npm
18
+ npm install @rivium/sync-node
19
+
20
+ # yarn
21
+ yarn add @rivium/sync-node
22
+
23
+ # pnpm
24
+ pnpm add @rivium/sync-node
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ```typescript
30
+ import { RiviumSyncAdmin } from '@rivium/sync-node';
31
+
32
+ // Initialize with your Project API Key and Server Secret
33
+ const riviumSync = new RiviumSyncAdmin({
34
+ apiKey: process.env.RIVIUM_SYNC_API_KEY, // nl_live_xxx or nl_test_xxx
35
+ serverSecret: process.env.RIVIUM_SYNC_SERVER_SECRET, // nl_srv_xxx - Required for server-side operations
36
+ });
37
+
38
+ // Get a database reference (database must be created via dashboard first)
39
+ const db = riviumSync.database('your-database-id');
40
+
41
+ // Get a collection reference
42
+ const users = db.collection('users');
43
+ ```
44
+
45
+ > **Note:** Both `apiKey` and `serverSecret` are required for all server-side SDK operations. You can find these credentials in your [AuthLeap Dashboard](https://console.authleap.com) when you create a project. Database creation and deletion is managed via the dashboard, not via SDK.
46
+
47
+ ## CRUD Operations
48
+
49
+ ### Create a Document
50
+
51
+ ```typescript
52
+ // Add with auto-generated ID
53
+ const newUser = await users.add({
54
+ name: 'John Doe',
55
+ email: 'john@example.com',
56
+ age: 28,
57
+ createdAt: new Date().toISOString(),
58
+ });
59
+ console.log('Created user with ID:', newUser.id);
60
+
61
+ // Set with specific ID
62
+ await users.doc('user-123').set({
63
+ name: 'Jane Doe',
64
+ email: 'jane@example.com',
65
+ });
66
+ ```
67
+
68
+ ### Read Documents
69
+
70
+ ```typescript
71
+ // Get a single document
72
+ const user = await users.get('user-123');
73
+ if (user) {
74
+ console.log('User name:', user.data.name);
75
+ }
76
+
77
+ // Check if document exists
78
+ const exists = await users.doc('user-123').exists();
79
+
80
+ // Get all documents
81
+ const allUsers = await users.getAll();
82
+ console.log('Total users:', allUsers.length);
83
+ ```
84
+
85
+ ### Update Documents
86
+
87
+ ```typescript
88
+ // Partial update (merge)
89
+ await users.doc('user-123').update({
90
+ age: 29,
91
+ updatedAt: new Date().toISOString(),
92
+ });
93
+
94
+ // Full replace
95
+ await users.doc('user-123').set({
96
+ name: 'John Updated',
97
+ email: 'john.new@example.com',
98
+ age: 29,
99
+ });
100
+ ```
101
+
102
+ ### Delete Documents
103
+
104
+ ```typescript
105
+ await users.doc('user-123').delete();
106
+ ```
107
+
108
+ ## Querying
109
+
110
+ ```typescript
111
+ // Build queries with fluent API
112
+ const adults = await users
113
+ .where('age', '>=', 18)
114
+ .where('status', '==', 'active')
115
+ .orderBy('createdAt', 'desc')
116
+ .limit(20)
117
+ .get();
118
+
119
+ // Get first result only
120
+ const firstUser = await users
121
+ .where('email', '==', 'john@example.com')
122
+ .query()
123
+ .getFirst();
124
+
125
+ // Count matching documents
126
+ const activeCount = await users
127
+ .where('status', '==', 'active')
128
+ .query()
129
+ .count();
130
+
131
+ // Pagination
132
+ const page1 = await users.orderBy('name').limit(10).get();
133
+ const page2 = await users.orderBy('name').limit(10).offset(10).get();
134
+ ```
135
+
136
+ ### Available Query Operators
137
+
138
+ | Operator | Description |
139
+ |----------|-------------|
140
+ | `==` | Equal |
141
+ | `!=` | Not equal |
142
+ | `<` | Less than |
143
+ | `<=` | Less than or equal |
144
+ | `>` | Greater than |
145
+ | `>=` | Greater than or equal |
146
+ | `in` | Value in array |
147
+ | `not-in` | Value not in array |
148
+ | `array-contains` | Array contains value |
149
+
150
+ ## Batch Operations
151
+
152
+ Execute multiple writes atomically:
153
+
154
+ ```typescript
155
+ const batch = riviumSync.batch();
156
+
157
+ // Add operations to the batch
158
+ batch.set(users.doc('user1'), { name: 'User 1', status: 'active' });
159
+ batch.update(users.doc('user2'), { lastSeen: new Date().toISOString() });
160
+ batch.delete(users.doc('user3'));
161
+
162
+ // Commit all operations
163
+ await batch.commit();
164
+ ```
165
+
166
+ ## Realtime Updates (Optional)
167
+
168
+ Enable realtime subscriptions for server-side event processing:
169
+
170
+ ```typescript
171
+ const riviumSync = new RiviumSyncAdmin({
172
+ apiKey: process.env.RIVIUM_SYNC_API_KEY!,
173
+ serverSecret: process.env.RIVIUM_SYNC_SERVER_SECRET!,
174
+ enableRealtime: true, // Enable MQTT connection
175
+ });
176
+
177
+ // Listen to a single document
178
+ const unsubscribe = users.doc('user-123').onSnapshot((user) => {
179
+ if (user) {
180
+ console.log('User updated:', user.data);
181
+ } else {
182
+ console.log('User was deleted');
183
+ }
184
+ });
185
+
186
+ // Listen to a collection
187
+ const unsubscribeAll = users.onSnapshot((allUsers) => {
188
+ console.log('Users changed, count:', allUsers.length);
189
+ });
190
+
191
+ // Listen to query results
192
+ const unsubscribeQuery = users
193
+ .where('status', '==', 'online')
194
+ .onSnapshot((onlineUsers) => {
195
+ console.log('Online users:', onlineUsers.length);
196
+ });
197
+
198
+ // Stop listening when done
199
+ unsubscribe();
200
+ unsubscribeAll();
201
+ unsubscribeQuery();
202
+ ```
203
+
204
+ ## Configuration Options
205
+
206
+ ```typescript
207
+ const riviumSync = new RiviumSyncAdmin({
208
+ // Required
209
+ apiKey: 'nl_live_xxxxxxxxxxxxxxxxxxxxx', // Required - from AuthLeap Dashboard
210
+ serverSecret: 'nl_srv_xxxxxxxxxxxxxxxxxxxxx', // Required - from AuthLeap Dashboard
211
+
212
+ // Optional
213
+ enableRealtime: false, // Enable MQTT subscriptions
214
+ logLevel: RiviumSyncLogLevel.ERROR, // Logging level
215
+ timeout: 30000, // Request timeout in ms
216
+ });
217
+ ```
218
+
219
+ ### Credentials
220
+
221
+ | Credential | Format | Description |
222
+ |------------|--------|-------------|
223
+ | **API Key** | `nl_live_xxx` or `nl_test_xxx` | Used for client-side SDKs and server-side SDKs |
224
+ | **Server Secret** | `nl_srv_xxx` | **Required** for server-side operations. Never expose in client-side code. |
225
+
226
+ Both credentials are generated when you create a project in the [AuthLeap Dashboard](https://console.authleap.com). Store them securely and never commit them to version control.
227
+
228
+ ### Log Levels
229
+
230
+ ```typescript
231
+ import { RiviumSyncLogLevel } from '@rivium/sync-node';
232
+
233
+ RiviumSyncLogLevel.NONE // No logs
234
+ RiviumSyncLogLevel.ERROR // Only errors
235
+ RiviumSyncLogLevel.WARNING // Errors and warnings
236
+ RiviumSyncLogLevel.INFO // General info
237
+ RiviumSyncLogLevel.DEBUG // Debug info
238
+ RiviumSyncLogLevel.VERBOSE // Everything
239
+ ```
240
+
241
+ ## TypeScript Support
242
+
243
+ Full TypeScript support with generics:
244
+
245
+ ```typescript
246
+ interface User {
247
+ name: string;
248
+ email: string;
249
+ age: number;
250
+ status: 'active' | 'inactive';
251
+ }
252
+
253
+ const users = db.collection<User>('users');
254
+
255
+ // All operations are now typed
256
+ const newUser = await users.add({
257
+ name: 'John',
258
+ email: 'john@example.com',
259
+ age: 28,
260
+ status: 'active',
261
+ });
262
+
263
+ // Type inference works
264
+ const user = await users.get('user-123');
265
+ if (user) {
266
+ console.log(user.data.name); // string
267
+ console.log(user.data.age); // number
268
+ }
269
+ ```
270
+
271
+ ## Error Handling
272
+
273
+ ```typescript
274
+ import { RiviumSyncError, RiviumSyncErrorCode } from '@rivium/sync-node';
275
+
276
+ try {
277
+ await users.get('nonexistent-id');
278
+ } catch (error) {
279
+ if (error instanceof RiviumSyncError) {
280
+ console.error('Error code:', error.code);
281
+ console.error('Message:', error.message);
282
+ console.error('Details:', error.details);
283
+
284
+ if (error.code === RiviumSyncErrorCode.DOCUMENT_NOT_FOUND) {
285
+ // Handle not found
286
+ }
287
+ }
288
+ }
289
+ ```
290
+
291
+ ## Use Cases
292
+
293
+ ### Backend API Server
294
+
295
+ ```typescript
296
+ // Express.js example
297
+ import express from 'express';
298
+ import { RiviumSyncAdmin } from '@rivium/sync-node';
299
+
300
+ const app = express();
301
+ const riviumSync = new RiviumSyncAdmin({
302
+ apiKey: process.env.RIVIUM_SYNC_API_KEY!,
303
+ serverSecret: process.env.RIVIUM_SYNC_SERVER_SECRET!,
304
+ });
305
+ const db = riviumSync.database('my-database');
306
+
307
+ app.get('/api/users', async (req, res) => {
308
+ const users = await db.collection('users').getAll();
309
+ res.json(users);
310
+ });
311
+
312
+ app.post('/api/users', async (req, res) => {
313
+ const user = await db.collection('users').add(req.body);
314
+ res.json(user);
315
+ });
316
+ ```
317
+
318
+ ### Serverless Functions
319
+
320
+ ```typescript
321
+ // AWS Lambda example
322
+ import { RiviumSyncAdmin } from '@rivium/sync-node';
323
+
324
+ const riviumSync = new RiviumSyncAdmin({
325
+ apiKey: process.env.RIVIUM_SYNC_API_KEY!,
326
+ serverSecret: process.env.RIVIUM_SYNC_SERVER_SECRET!,
327
+ });
328
+
329
+ export async function handler(event) {
330
+ const db = riviumSync.database('my-database');
331
+ const users = await db.collection('users')
332
+ .where('status', '==', 'active')
333
+ .get();
334
+
335
+ return {
336
+ statusCode: 200,
337
+ body: JSON.stringify(users),
338
+ };
339
+ }
340
+ ```
341
+
342
+ ### Data Migration Script
343
+
344
+ ```typescript
345
+ import { RiviumSyncAdmin } from '@rivium/sync-node';
346
+
347
+ const riviumSync = new RiviumSyncAdmin({
348
+ apiKey: process.env.RIVIUM_SYNC_API_KEY!,
349
+ serverSecret: process.env.RIVIUM_SYNC_SERVER_SECRET!,
350
+ });
351
+ const db = riviumSync.database('my-database');
352
+
353
+ async function migrate() {
354
+ const users = await db.collection('users').getAll();
355
+
356
+ const batch = riviumSync.batch();
357
+ for (const user of users) {
358
+ // Add migration logic
359
+ batch.update(db.collection('users').doc(user.id), {
360
+ migratedAt: new Date().toISOString(),
361
+ version: 2,
362
+ });
363
+ }
364
+
365
+ await batch.commit();
366
+ console.log('Migration complete!');
367
+ }
368
+
369
+ migrate();
370
+ ```
371
+
372
+ ## API Reference
373
+
374
+ ### RiviumSyncAdmin
375
+
376
+ | Method | Description |
377
+ |--------|-------------|
378
+ | `database(id)` | Get a database reference |
379
+ | `batch()` | Create a write batch |
380
+ | `disconnect()` | Disconnect from realtime |
381
+ | `setLogLevel(level)` | Change log level |
382
+
383
+ ### SyncDatabase
384
+
385
+ | Method | Description |
386
+ |--------|-------------|
387
+ | `collection<T>(id)` | Get a typed collection reference |
388
+
389
+ ### SyncCollection
390
+
391
+ | Method | Description |
392
+ |--------|-------------|
393
+ | `doc(id)` | Get a document reference |
394
+ | `add(data)` | Create document with auto ID |
395
+ | `get(id)` | Get a single document |
396
+ | `getAll(options?)` | Get all documents |
397
+ | `where(field, op, value)` | Start a query |
398
+ | `orderBy(field, direction?)` | Start a sorted query |
399
+ | `limit(count)` | Start a limited query |
400
+ | `query()` | Get query builder |
401
+ | `onSnapshot(callback, options?)` | Listen to changes |
402
+
403
+ ### SyncDocumentRef
404
+
405
+ | Method | Description |
406
+ |--------|-------------|
407
+ | `get()` | Get document data |
408
+ | `exists()` | Check if document exists |
409
+ | `set(data)` | Set document (overwrite) |
410
+ | `update(data)` | Update document (merge) |
411
+ | `delete()` | Delete document |
412
+ | `onSnapshot(callback)` | Listen to changes |
413
+
414
+ ### SyncQuery
415
+
416
+ | Method | Description |
417
+ |--------|-------------|
418
+ | `where(field, op, value)` | Add filter |
419
+ | `orderBy(field, direction?)` | Set ordering |
420
+ | `limit(count)` | Limit results |
421
+ | `offset(count)` | Skip results |
422
+ | `startAfter(count)` | Alias for offset |
423
+ | `get()` | Execute query |
424
+ | `getFirst()` | Get first result |
425
+ | `count()` | Count results |
426
+ | `onSnapshot(callback)` | Listen to query |
427
+
428
+ ### WriteBatch
429
+
430
+ | Method | Description |
431
+ |--------|-------------|
432
+ | `set(docRef, data)` | Add set operation |
433
+ | `update(docRef, data)` | Add update operation |
434
+ | `delete(docRef)` | Add delete operation |
435
+ | `commit()` | Execute all operations |
436
+ | `size` | Number of pending operations |
437
+
438
+ ## License
439
+
440
+ MIT