@seaverse/dataservice 1.1.0 → 1.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 CHANGED
@@ -1,6 +1,15 @@
1
- # SeaVerse Data Service SDK
1
+ # @seaverse/dataservice
2
2
 
3
- TypeScript/JavaScript SDK for universal data storage with PostgREST.
3
+ A TypeScript/JavaScript SDK for universal data storage with PostgREST backend. Store and query JSON data with automatic user isolation and type safety.
4
+
5
+ ## Features
6
+
7
+ - **Type-safe**: Full TypeScript support with generic types
8
+ - **Secure**: Built on PostgreSQL Row-Level Security (RLS)
9
+ - **Flexible**: Store any JSON data structure
10
+ - **Query builder**: Fluent API for complex queries
11
+ - **Auto-extraction**: Automatically extracts app ID from URL
12
+ - **UUID support**: Client-side or server-side ID generation
4
13
 
5
14
  ## Installation
6
15
 
@@ -13,169 +22,260 @@ npm install @seaverse/dataservice
13
22
  ```typescript
14
23
  import { createClient } from '@seaverse/dataservice';
15
24
 
16
- // appId is automatically extracted from current URL
25
+ // Create client (uses default SeaVerse API, appId auto-extracted from URL)
17
26
  const client = createClient({
18
- url: 'https://your-postgrest-api.example.com',
19
- token: 'Bearer your-jwt-token-here',
27
+ token: 'Bearer your-jwt-token',
20
28
  });
21
29
 
22
- // Insert
23
- const order = await client.userData
24
- .collection('orders')
25
- .insert({
26
- order_number: 'ORD-001',
27
- status: 'pending',
28
- total: 99.99,
29
- });
30
+ // Access user data table
31
+ const orders = client.userData.collection('orders');
30
32
 
31
- // Get by ID
32
- const record = await client.userData
33
- .collection('orders')
34
- .get(order.id);
33
+ // Insert data
34
+ const order = await orders.insert({
35
+ order_number: 'ORD-001',
36
+ status: 'pending',
37
+ total: 99.99,
38
+ });
35
39
 
36
- // Query
37
- const results = await client.userData
38
- .collection('orders')
40
+ // Query data
41
+ const pending = await orders
39
42
  .select()
40
43
  .eq('data->>status', 'pending')
41
44
  .order('created_at', { descending: true })
42
- .limit(10)
43
45
  .execute();
44
46
 
45
- // Update
46
- await client.userData
47
- .collection('orders')
48
- .patch(order.id, { status: 'completed' });
47
+ // Update data
48
+ await orders.patch(order.id, { status: 'completed' });
49
49
 
50
- // Delete
51
- await client.userData
52
- .collection('orders')
53
- .delete(order.id);
50
+ // Delete data
51
+ await orders.delete(order.id);
54
52
  ```
55
53
 
56
54
  ## Core Concepts
57
55
 
58
- ### Hierarchy
56
+ ### Data Hierarchy
59
57
 
60
58
  ```
61
- Client → DataTable (user_data) → Collection (collection_name) → Data (JSONB)
59
+ DataServiceClient
60
+ └── DataTable (e.g., userData)
61
+ └── Collection (e.g., "orders")
62
+ └── DataRecord (JSONB data + metadata)
62
63
  ```
63
64
 
64
- ### Application ID (appId)
65
+ ### Application ID
65
66
 
66
- **Automatic Extraction**: The SDK automatically extracts `app_id` from the current URL:
67
+ The SDK automatically extracts `app_id` from the current environment:
67
68
 
69
+ **Browser**: Extracted from URL hostname
68
70
  ```
69
- URL: https://app_8e5e867e-user_f4ed2364ffcf24d6c6707d5ca5e4fe6d.app.seaverse.ai
70
- → appId: app_8e5e867e-user_f4ed2364ffcf24d6c6707d5ca5e4fe6d
71
-
72
- URL: https://example.com
73
- → appId: example.com
71
+ https://app_8e5e867e-user_f4ed2364.app.seaverse.ai
72
+ → appId: "app_8e5e867e-user_f4ed2364"
74
73
  ```
75
74
 
76
- **Node.js Environment**: Set via environment variable:
75
+ **Node.js**: Set via environment variable
77
76
  ```bash
78
77
  export SEAVERSE_APP_ID=my-app-id
79
78
  ```
80
79
 
81
- ### Unique Constraint
80
+ Access the extracted ID:
81
+ ```typescript
82
+ console.log(client.appId); // "app_8e5e867e-user_f4ed2364"
83
+ ```
84
+
85
+ ### Data Tables
86
+
87
+ The SDK provides access to different data tables with different permission scopes:
88
+
89
+ - **`userData`**: User-specific data (isolated by user_id)
90
+ - More tables coming soon (public data, shared data, etc.)
82
91
 
83
- **Important**: Only ONE record per `(user_id, app_id, collection_name)`.
92
+ ### Collections
84
93
 
85
- For multiple records, use unique collection names:
94
+ Collections are logical groupings within a table. Each collection stores one record per `(user_id, app_id, collection_name)` combination.
95
+
96
+ **Important**: To store multiple records, use unique collection names:
86
97
 
87
98
  ```typescript
88
- // ✓ Correct
89
- await client.userData.collection('orders_1').insert(order1);
90
- await client.userData.collection('orders_2').insert(order2);
99
+ // ✓ Correct: Unique collection names
100
+ await client.userData.collection('order_1').insert(order1);
101
+ await client.userData.collection('order_2').insert(order2);
102
+
103
+ // ✓ Or use batch insert helper
104
+ await client.userData.batchInsert('order', [order1, order2]);
105
+ // Creates: order_0, order_1, order_2, ...
106
+
107
+ // ✗ Wrong: Same collection name
108
+ await client.userData.collection('order').insert(order1);
109
+ await client.userData.collection('order').insert(order2); // Error: 409 Conflict
110
+ ```
91
111
 
92
- // Or use batch insert
93
- await client.userData.batchInsert('orders', [order1, order2]);
112
+ ### Data Records
94
113
 
95
- // Wrong - will fail
96
- await client.userData.collection('orders').insert(order1);
97
- await client.userData.collection('orders').insert(order2); // Error: 409 Conflict
114
+ Each record contains:
115
+
116
+ ```typescript
117
+ interface DataRecord<T> {
118
+ id: string; // UUID primary key
119
+ user_id: string; // Owner user ID
120
+ app_id: string; // Application ID
121
+ collection_name: string; // Collection identifier
122
+ data: T; // Your JSON data
123
+ created_at: string; // ISO timestamp
124
+ updated_at: string; // ISO timestamp
125
+ deleted_at: string | null; // Soft delete timestamp
126
+ }
98
127
  ```
99
128
 
100
129
  ## API Reference
101
130
 
102
- ### Client
131
+ ### Client Creation
103
132
 
104
133
  ```typescript
105
- createClient(config: ClientConfig): DataServiceClient
134
+ import { createClient } from '@seaverse/dataservice';
106
135
 
107
- interface ClientConfig {
108
- url: string; // PostgREST API URL
109
- token: string; // JWT token with user_id in payload
136
+ const client = createClient({
137
+ token: string; // JWT token (must contain user_id)
138
+ url?: string; // PostgREST API URL (default: https://dataservice-api.seaverse.ai)
110
139
  options?: {
111
- timeout?: number; // Request timeout (ms, default: 30000)
112
- headers?: Record<string, string>;
140
+ timeout?: number; // Request timeout in ms (default: 30000)
141
+ headers?: Record<string, string>; // Additional headers
113
142
  };
114
- }
143
+ });
144
+ ```
145
+
146
+ **Examples:**
147
+
148
+ ```typescript
149
+ // Use default SeaVerse API
150
+ const client = createClient({
151
+ token: 'Bearer your-jwt-token',
152
+ });
115
153
 
116
- // Client properties
117
- client.appId: string // Auto-extracted from URL
118
- client.userData: DataTable
154
+ // Use custom API endpoint
155
+ const client = createClient({
156
+ url: 'https://your-custom-api.example.com',
157
+ token: 'Bearer your-jwt-token',
158
+ });
119
159
  ```
120
160
 
121
- ### DataTable
161
+ ### DataTable Methods
122
162
 
123
163
  ```typescript
164
+ // Get a collection
124
165
  client.userData.collection<T>(name: string): Collection<T>
125
- client.userData.batchInsert<T>(baseName: string, records: T[]): Promise<DataRecord<T>[]>
166
+
167
+ // Batch insert multiple records
168
+ client.userData.batchInsert<T>(
169
+ baseName: string,
170
+ records: T[]
171
+ ): Promise<DataRecord<T>[]>
126
172
  ```
127
173
 
128
- ### Collection
174
+ ### Collection Methods
175
+
176
+ #### Create
129
177
 
130
178
  ```typescript
131
- // Create
132
- collection.insert(data: T, id?: string): Promise<DataRecord<T>> // Optional UUID
179
+ // Insert with auto-generated UUID
180
+ collection.insert(data: T): Promise<DataRecord<T>>
181
+
182
+ // Insert with custom UUID
183
+ collection.insert(data: T, id: string): Promise<DataRecord<T>>
184
+ ```
133
185
 
134
- // Read
186
+ #### Read
187
+
188
+ ```typescript
189
+ // Get by ID
135
190
  collection.get(id: string): Promise<DataRecord<T> | null>
136
191
  collection.selectById(id: string): Promise<DataRecord<T> | null>
192
+
193
+ // Query builder
137
194
  collection.select(): QueryBuilder<T>
195
+
196
+ // Search by criteria
138
197
  collection.search(criteria: Partial<T>): Promise<DataRecord<T>[]>
198
+
199
+ // Count records
139
200
  collection.count(): Promise<number>
201
+ ```
202
+
203
+ #### Update
140
204
 
141
- // Update
205
+ ```typescript
206
+ // Full update (replaces entire data object)
142
207
  collection.update(id: string, data: T): Promise<DataRecord<T>>
208
+
209
+ // Partial update (merges with existing data)
143
210
  collection.patch(id: string, partial: Partial<T>): Promise<DataRecord<T>>
211
+ ```
212
+
213
+ #### Delete
144
214
 
145
- // Delete
215
+ ```typescript
216
+ // Hard delete (permanent)
146
217
  collection.delete(id: string): Promise<void>
218
+
219
+ // Soft delete (sets deleted_at timestamp)
147
220
  collection.softDelete(id: string): Promise<boolean>
221
+
222
+ // Restore soft-deleted record
148
223
  collection.restore(id: string): Promise<boolean>
149
224
  ```
150
225
 
151
- **Note**: All IDs are UUIDs (strings). Database auto-generates if not provided.
152
-
153
226
  ### Query Builder
154
227
 
228
+ Build complex queries with a fluent API:
229
+
155
230
  ```typescript
156
- query
157
- .eq(field, value) // Equal
158
- .neq(field, value) // Not equal
159
- .gt(field, value) // Greater than
160
- .gte(field, value) // Greater than or equal
161
- .lt(field, value) // Less than
162
- .lte(field, value) // Less than or equal
163
- .like(field, pattern) // Pattern match (case-sensitive)
164
- .ilike(field, pattern) // Pattern match (case-insensitive)
165
- .in(field, values) // Value in array
166
- .contains(value) // JSONB contains
167
- .order(field, options) // Sort
168
- .limit(count) // Limit results
169
- .offset(count) // Skip results
170
- .execute() // Get results
171
- .count() // Get count
231
+ collection.select()
232
+ // Comparison operators
233
+ .eq(field: string, value: any) // Equal
234
+ .neq(field: string, value: any) // Not equal
235
+ .gt(field: string, value: any) // Greater than
236
+ .gte(field: string, value: any) // Greater than or equal
237
+ .lt(field: string, value: any) // Less than
238
+ .lte(field: string, value: any) // Less than or equal
239
+
240
+ // Pattern matching
241
+ .like(field: string, pattern: string) // Case-sensitive
242
+ .ilike(field: string, pattern: string) // Case-insensitive
243
+
244
+ // Array operations
245
+ .in(field: string, values: any[]) // Value in array
246
+
247
+ // JSONB operations
248
+ .contains(value: any) // JSONB contains
249
+
250
+ // Sorting and pagination
251
+ .order(field: string, options?: { descending?: boolean })
252
+ .limit(count: number)
253
+ .offset(count: number)
254
+
255
+ // Execute
256
+ .execute(): Promise<DataRecord<T>[]>
257
+ .count(): Promise<number>
172
258
  ```
173
259
 
174
- ### Client Methods
260
+ **Field syntax for JSONB queries**:
261
+ - Use `data->>field` for text comparison: `.eq('data->>status', 'pending')`
262
+ - Use `data->field` for numeric comparison: `.gt('data->total', '100')`
263
+
264
+ ### Client Utility Methods
175
265
 
176
266
  ```typescript
177
- client.getStats(): Promise<UserDataStats>
178
- client.health(): Promise<{ status: string; user_id: string }>
267
+ // Get user data statistics
268
+ client.getStats(): Promise<{
269
+ total_records: number;
270
+ total_collections: number;
271
+ storage_bytes: number;
272
+ }>
273
+
274
+ // Health check
275
+ client.health(): Promise<{
276
+ status: string;
277
+ user_id: string;
278
+ }>
179
279
  ```
180
280
 
181
281
  ## Examples
@@ -183,102 +283,174 @@ client.health(): Promise<{ status: string; user_id: string }>
183
283
  ### E-Commerce Orders
184
284
 
185
285
  ```typescript
286
+ import { createClient } from '@seaverse/dataservice';
287
+
186
288
  type Order = {
187
289
  order_number: string;
188
290
  customer_email: string;
189
- items: Array<{ product_id: string; quantity: number; price: number }>;
291
+ items: Array<{
292
+ product_id: string;
293
+ quantity: number;
294
+ price: number;
295
+ }>;
190
296
  status: 'pending' | 'processing' | 'shipped' | 'delivered';
191
297
  total: number;
298
+ notes?: string;
192
299
  };
193
300
 
301
+ const client = createClient({
302
+ token: process.env.JWT_TOKEN!,
303
+ });
304
+
194
305
  const orders = client.userData.collection<Order>('orders');
195
306
 
196
- // Create
307
+ // Create order
197
308
  const order = await orders.insert({
198
309
  order_number: `ORD-${Date.now()}`,
199
310
  customer_email: 'customer@example.com',
200
- items: [{ product_id: 'PROD-001', quantity: 2, price: 29.99 }],
311
+ items: [
312
+ { product_id: 'PROD-001', quantity: 2, price: 29.99 },
313
+ { product_id: 'PROD-002', quantity: 1, price: 49.99 },
314
+ ],
201
315
  status: 'pending',
202
- total: 59.98,
316
+ total: 109.97,
203
317
  });
204
318
 
205
- // Query
206
- const pending = await orders
319
+ console.log('Order created:', order.id);
320
+
321
+ // Query pending orders over $50
322
+ const pendingOrders = await orders
207
323
  .select()
208
324
  .eq('data->>status', 'pending')
209
- .gt('data->>total', '50')
325
+ .gt('data->total', '50')
210
326
  .order('created_at', { descending: true })
327
+ .limit(10)
211
328
  .execute();
212
329
 
213
- // Update
330
+ console.log(`Found ${pendingOrders.length} pending orders`);
331
+
332
+ // Update order status
214
333
  await orders.patch(order.id, { status: 'shipped' });
334
+
335
+ // Search by customer email
336
+ const customerOrders = await orders.search({
337
+ customer_email: 'customer@example.com',
338
+ });
215
339
  ```
216
340
 
217
- ### GPT Conversations
341
+ ### Chat Conversations
218
342
 
219
343
  ```typescript
344
+ type Message = {
345
+ role: 'user' | 'assistant' | 'system';
346
+ content: string;
347
+ timestamp: string;
348
+ };
349
+
220
350
  type Conversation = {
221
351
  title: string;
222
352
  model: string;
223
- messages: Array<{
224
- role: 'user' | 'assistant' | 'system';
225
- content: string;
226
- timestamp: string;
227
- }>;
353
+ messages: Message[];
354
+ metadata?: {
355
+ tokens_used?: number;
356
+ cost?: number;
357
+ };
228
358
  };
229
359
 
230
360
  const conversations = client.userData.collection<Conversation>('chats');
231
361
 
362
+ // Create conversation
232
363
  const conv = await conversations.insert({
233
- title: 'Project Planning',
364
+ title: 'Project Planning Discussion',
234
365
  model: 'claude-3-opus',
235
366
  messages: [
236
367
  {
237
368
  role: 'user',
238
- content: 'Help me plan a new feature',
369
+ content: 'Help me plan a new feature for my app',
239
370
  timestamp: new Date().toISOString(),
240
371
  },
241
372
  ],
242
373
  });
243
374
 
244
- // Add message
245
- const retrieved = await conversations.get(conv.id);
246
- await conversations.patch(conv.id, {
247
- messages: [
248
- ...retrieved!.data.messages,
249
- {
250
- role: 'assistant',
251
- content: 'I can help you with that...',
252
- timestamp: new Date().toISOString(),
253
- },
254
- ],
375
+ // Add assistant response
376
+ const current = await conversations.get(conv.id);
377
+ if (current) {
378
+ await conversations.patch(conv.id, {
379
+ messages: [
380
+ ...current.data.messages,
381
+ {
382
+ role: 'assistant',
383
+ content: 'I can help you with that. What feature are you thinking about?',
384
+ timestamp: new Date().toISOString(),
385
+ },
386
+ ],
387
+ });
388
+ }
389
+
390
+ // List recent conversations
391
+ const recent = await conversations
392
+ .select()
393
+ .order('updated_at', { descending: true })
394
+ .limit(20)
395
+ .execute();
396
+ ```
397
+
398
+ ### User Preferences
399
+
400
+ ```typescript
401
+ type UserPreferences = {
402
+ theme: 'light' | 'dark' | 'auto';
403
+ language: string;
404
+ notifications: {
405
+ email: boolean;
406
+ push: boolean;
407
+ sms: boolean;
408
+ };
409
+ privacy: {
410
+ profile_visible: boolean;
411
+ show_activity: boolean;
412
+ };
413
+ };
414
+
415
+ const prefs = client.userData.collection<UserPreferences>('preferences');
416
+
417
+ // Initialize preferences
418
+ await prefs.insert({
419
+ theme: 'auto',
420
+ language: 'en',
421
+ notifications: {
422
+ email: true,
423
+ push: true,
424
+ sms: false,
425
+ },
426
+ privacy: {
427
+ profile_visible: true,
428
+ show_activity: false,
429
+ },
255
430
  });
431
+
432
+ // Update theme only
433
+ await prefs.patch(prefId, { theme: 'dark' });
256
434
  ```
257
435
 
258
436
  ## UUID Primary Keys
259
437
 
260
- All records use UUID strings as primary keys:
438
+ All records use UUID strings as primary keys.
439
+
440
+ ### Auto-generated UUIDs
261
441
 
262
442
  ```typescript
263
- // Database auto-generates UUID
264
443
  const order = await orders.insert({
265
444
  order_number: 'ORD-001',
266
445
  status: 'pending',
267
446
  });
268
- console.log(order.id); // "550e8400-e29b-41d4-a716-446655440000"
269
-
270
- // Or provide your own UUID
271
- import { randomUUID } from 'crypto';
272
447
 
273
- const customId = randomUUID();
274
- const order2 = await orders.insert(
275
- { order_number: 'ORD-002', status: 'pending' },
276
- customId
277
- );
278
- console.log(order2.id === customId); // true
448
+ console.log(order.id); // "550e8400-e29b-41d4-a716-446655440000"
279
449
  ```
280
450
 
281
- **Client-side UUID generation** (recommended for offline-first apps):
451
+ ### Custom UUIDs
452
+
453
+ Useful for offline-first applications or client-side ID generation:
282
454
 
283
455
  ```typescript
284
456
  // Node.js
@@ -288,29 +460,40 @@ const id = randomUUID();
288
460
  // Browser
289
461
  const id = crypto.randomUUID();
290
462
 
291
- // TypeScript with uuid library
463
+ // With uuid library
292
464
  import { v4 as uuidv4 } from 'uuid';
293
465
  const id = uuidv4();
466
+
467
+ // Use custom ID
468
+ const order = await orders.insert(
469
+ { order_number: 'ORD-002', status: 'pending' },
470
+ id
471
+ );
294
472
  ```
295
473
 
296
474
  ## TypeScript Support
297
475
 
476
+ Full type safety with generic types:
477
+
298
478
  ```typescript
299
- type MyData = {
479
+ type Product = {
300
480
  name: string;
301
- count: number;
481
+ price: number;
482
+ in_stock: boolean;
302
483
  };
303
484
 
304
- const collection = client.userData.collection<MyData>('items');
485
+ const products = client.userData.collection<Product>('products');
305
486
 
306
- const record = await collection.insert({
307
- name: 'Item 1',
308
- count: 42,
487
+ const product = await products.insert({
488
+ name: 'Widget',
489
+ price: 29.99,
490
+ in_stock: true,
309
491
  });
310
492
 
311
493
  // TypeScript knows the shape
312
- console.log(record.data.name); // ✓ OK
313
- console.log(record.data.invalid); // TypeScript error
494
+ console.log(product.data.name); // ✓ string
495
+ console.log(product.data.price); // number
496
+ console.log(product.data.invalid); // ✗ TypeScript error
314
497
  ```
315
498
 
316
499
  ## Error Handling
@@ -322,26 +505,64 @@ try {
322
505
  await collection.insert(data);
323
506
  } catch (error) {
324
507
  if (error instanceof DataServiceError) {
325
- console.error('Code:', error.code);
508
+ console.error('Error code:', error.code);
326
509
  console.error('Message:', error.message);
327
- console.error('Status:', error.statusCode);
328
-
329
- if (error.code === '23505') {
330
- // Unique constraint violation
331
- console.log('Collection name already exists');
510
+ console.error('HTTP status:', error.statusCode);
511
+
512
+ // Handle specific errors
513
+ switch (error.code) {
514
+ case '23505':
515
+ console.log('Duplicate collection name - use a different name');
516
+ break;
517
+ case 'PGRST301':
518
+ console.log('Authentication failed - check your token');
519
+ break;
520
+ default:
521
+ console.log('Unexpected error:', error.message);
332
522
  }
523
+ } else {
524
+ console.error('Unknown error:', error);
333
525
  }
334
526
  }
335
527
  ```
336
528
 
529
+ Common error codes:
530
+ - `23505`: Unique constraint violation (duplicate collection name)
531
+ - `PGRST301`: JWT authentication failed
532
+ - `PGRST204`: No rows returned
533
+ - `PGRST116`: Invalid query syntax
534
+
535
+ ## Security
536
+
537
+ The SDK is built on PostgreSQL Row-Level Security (RLS):
538
+
539
+ - **JWT Authentication**: User identity from JWT token payload
540
+ - **Automatic Isolation**: Each user can only access their own data
541
+ - **No Admin Bypass**: Even database admins respect RLS policies
542
+ - **Secure by Default**: No configuration needed
543
+
544
+ Your JWT token must include a `user_id` claim:
545
+
546
+ ```json
547
+ {
548
+ "user_id": "user_f4ed2364ffcf24d6c6707d5ca5e4fe6d",
549
+ "exp": 1735689600
550
+ }
551
+ ```
552
+
337
553
  ## Development
338
554
 
339
555
  ### Setup
340
556
 
341
557
  ```bash
558
+ # Clone repository
342
559
  git clone https://github.com/seaverse/dataservice
343
560
  cd dataservice
561
+
562
+ # Install dependencies
344
563
  npm install
564
+
565
+ # Build
345
566
  npm run build
346
567
  ```
347
568
 
@@ -351,7 +572,7 @@ npm run build
351
572
  # Copy environment template
352
573
  cp .env.example .env
353
574
 
354
- # Edit .env with your credentials
575
+ # Configure your credentials
355
576
  # POSTGREST_URL=https://your-api.example.com
356
577
  # JWT_TOKEN=Bearer your-token-here
357
578
 
@@ -364,26 +585,15 @@ npm run test:examples
364
585
  - `npm run build` - Build the SDK
365
586
  - `npm run dev` - Build in watch mode
366
587
  - `npm run test:examples` - Run integration tests
367
- - `npm run lint` - Lint code
368
- - `npm run format` - Format code
369
-
370
- ## Security
371
-
372
- Built on PostgreSQL Row-Level Security (RLS):
373
- - JWT authentication with user_id in payload
374
- - Automatic data isolation per user
375
- - No admin bypass
376
-
377
- ## Contributing
378
-
379
- See [CONTRIBUTING.md](CONTRIBUTING.md)
588
+ - `npm run lint` - Lint code with ESLint
589
+ - `npm run format` - Format code with Prettier
380
590
 
381
591
  ## License
382
592
 
383
- MIT - See [LICENSE](LICENSE)
593
+ MIT
384
594
 
385
595
  ## Links
386
596
 
387
- - [GitHub](https://github.com/seaverse/dataservice)
388
- - [Issues](https://github.com/seaverse/dataservice/issues)
389
- - [AI Usage Guide](AI-USAGE-GUIDE.md)
597
+ - [GitHub Repository](https://github.com/seaverse/dataservice)
598
+ - [Report Issues](https://github.com/seaverse/dataservice/issues)
599
+ - [SeaVerse Platform](https://seaverse.ai)
package/dist/index.d.mts CHANGED
@@ -12,14 +12,13 @@
12
12
  * @example
13
13
  * ```typescript
14
14
  * const config: ClientConfig = {
15
- * url: 'https://your-postgrest-api.example.com',
16
15
  * token: 'Bearer your-jwt-token-here',
17
16
  * };
18
17
  * ```
19
18
  */
20
19
  interface ClientConfig {
21
- /** PostgREST API base URL */
22
- url: string;
20
+ /** PostgREST API base URL (default: https://dataservice-api.seaverse.ai) */
21
+ url?: string;
23
22
  /** JWT token containing user_id in payload.user_id */
24
23
  token: string;
25
24
  /** Optional configuration */
@@ -250,11 +249,17 @@ interface DataServiceClient {
250
249
  *
251
250
  * AI-friendly: Single entry point with clear configuration
252
251
  *
253
- * @param config - Client configuration with URL and JWT token
252
+ * @param config - Client configuration with JWT token (URL defaults to https://dataservice-api.seaverse.ai)
254
253
  * @returns DataServiceClient instance
255
254
  *
256
255
  * @example
257
256
  * ```typescript
257
+ * // Use default SeaVerse API endpoint
258
+ * const client = createClient({
259
+ * token: 'Bearer your-jwt-token-here',
260
+ * });
261
+ *
262
+ * // Or specify custom endpoint
258
263
  * const client = createClient({
259
264
  * url: 'https://your-postgrest-api.example.com',
260
265
  * token: 'Bearer your-jwt-token-here',
@@ -277,15 +282,15 @@ declare function createClient(config: ClientConfig): DataServiceClient;
277
282
  *
278
283
  * @example Basic Usage
279
284
  * ```typescript
280
- * import { createClient } from '@seaverse/data-service-sdk';
285
+ * import { createClient } from '@seaverse/dataservice';
281
286
  *
282
- * // appId is automatically extracted from current URL
287
+ * // Create client (uses default SeaVerse API)
283
288
  * const client = createClient({
284
- * url: 'https://postgrest.example.com',
285
- * token: 'your-jwt-token',
289
+ * token: 'Bearer your-jwt-token',
286
290
  * });
287
291
  *
288
- * // Insert data - appId is automatically included
292
+ * // appId is automatically extracted from current URL
293
+ * // Insert data
289
294
  * const order = await client.userData.collection('orders').insert({
290
295
  * order_number: 'ORD-123',
291
296
  * status: 'pending',
@@ -296,7 +301,7 @@ declare function createClient(config: ClientConfig): DataServiceClient;
296
301
  * const orders = await client.userData
297
302
  * .collection('orders')
298
303
  * .select()
299
- * .eq('status', 'pending')
304
+ * .eq('data->>status', 'pending')
300
305
  * .order('created_at', { descending: true })
301
306
  * .limit(10)
302
307
  * .execute();
package/dist/index.d.ts CHANGED
@@ -12,14 +12,13 @@
12
12
  * @example
13
13
  * ```typescript
14
14
  * const config: ClientConfig = {
15
- * url: 'https://your-postgrest-api.example.com',
16
15
  * token: 'Bearer your-jwt-token-here',
17
16
  * };
18
17
  * ```
19
18
  */
20
19
  interface ClientConfig {
21
- /** PostgREST API base URL */
22
- url: string;
20
+ /** PostgREST API base URL (default: https://dataservice-api.seaverse.ai) */
21
+ url?: string;
23
22
  /** JWT token containing user_id in payload.user_id */
24
23
  token: string;
25
24
  /** Optional configuration */
@@ -250,11 +249,17 @@ interface DataServiceClient {
250
249
  *
251
250
  * AI-friendly: Single entry point with clear configuration
252
251
  *
253
- * @param config - Client configuration with URL and JWT token
252
+ * @param config - Client configuration with JWT token (URL defaults to https://dataservice-api.seaverse.ai)
254
253
  * @returns DataServiceClient instance
255
254
  *
256
255
  * @example
257
256
  * ```typescript
257
+ * // Use default SeaVerse API endpoint
258
+ * const client = createClient({
259
+ * token: 'Bearer your-jwt-token-here',
260
+ * });
261
+ *
262
+ * // Or specify custom endpoint
258
263
  * const client = createClient({
259
264
  * url: 'https://your-postgrest-api.example.com',
260
265
  * token: 'Bearer your-jwt-token-here',
@@ -277,15 +282,15 @@ declare function createClient(config: ClientConfig): DataServiceClient;
277
282
  *
278
283
  * @example Basic Usage
279
284
  * ```typescript
280
- * import { createClient } from '@seaverse/data-service-sdk';
285
+ * import { createClient } from '@seaverse/dataservice';
281
286
  *
282
- * // appId is automatically extracted from current URL
287
+ * // Create client (uses default SeaVerse API)
283
288
  * const client = createClient({
284
- * url: 'https://postgrest.example.com',
285
- * token: 'your-jwt-token',
289
+ * token: 'Bearer your-jwt-token',
286
290
  * });
287
291
  *
288
- * // Insert data - appId is automatically included
292
+ * // appId is automatically extracted from current URL
293
+ * // Insert data
289
294
  * const order = await client.userData.collection('orders').insert({
290
295
  * order_number: 'ORD-123',
291
296
  * status: 'pending',
@@ -296,7 +301,7 @@ declare function createClient(config: ClientConfig): DataServiceClient;
296
301
  * const orders = await client.userData
297
302
  * .collection('orders')
298
303
  * .select()
299
- * .eq('status', 'pending')
304
+ * .eq('data->>status', 'pending')
300
305
  * .order('created_at', { descending: true })
301
306
  * .limit(10)
302
307
  * .execute();
package/dist/index.js CHANGED
@@ -57,7 +57,7 @@ var HTTPClient = class {
57
57
  fetchFn;
58
58
  timeout;
59
59
  constructor(config) {
60
- this.baseUrl = config.url.replace(/\/$/, "");
60
+ this.baseUrl = (config.url || "https://dataservice-api.seaverse.ai").replace(/\/$/, "");
61
61
  this.fetchFn = config.options?.fetch || globalThis.fetch;
62
62
  this.timeout = config.options?.timeout || 3e4;
63
63
  this.headers = {
package/dist/index.mjs CHANGED
@@ -29,7 +29,7 @@ var HTTPClient = class {
29
29
  fetchFn;
30
30
  timeout;
31
31
  constructor(config) {
32
- this.baseUrl = config.url.replace(/\/$/, "");
32
+ this.baseUrl = (config.url || "https://dataservice-api.seaverse.ai").replace(/\/$/, "");
33
33
  this.fetchFn = config.options?.fetch || globalThis.fetch;
34
34
  this.timeout = config.options?.timeout || 3e4;
35
35
  this.headers = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seaverse/dataservice",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "AI-Friendly Universal Data Storage SDK for TypeScript/JavaScript",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -35,13 +35,12 @@
35
35
  "license": "MIT",
36
36
  "repository": {
37
37
  "type": "git",
38
- "url": "https://github.com/seaverseai/sv-sdk.git",
39
- "directory": "packages/dataservice"
38
+ "url": "https://github.com/seaverse/dataservice.git"
40
39
  },
41
40
  "bugs": {
42
- "url": "https://github.com/seaverseai/sv-sdk/issues"
41
+ "url": "https://github.com/seaverse/dataservice/issues"
43
42
  },
44
- "homepage": "https://github.com/seaverseai/sv-sdk/tree/main/packages/dataservice#readme",
43
+ "homepage": "https://github.com/seaverse/dataservice#readme",
45
44
  "devDependencies": {
46
45
  "@types/node": "^20.11.0",
47
46
  "@typescript-eslint/eslint-plugin": "^6.19.0",