@vaiftechnologies/vaif-client 0.1.1 → 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2026 VAIF Technologies
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,554 @@
1
+ # @vaiftechnologies/vaif-client
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@vaiftechnologies/vaif-client)](https://www.npmjs.com/package/@vaiftechnologies/vaif-client)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-4.7+-blue)](https://www.typescriptlang.org/)
6
+
7
+ The official JavaScript/TypeScript SDK for VAIF Studio - the AI-powered backend platform. Database, auth, realtime, storage, functions, AI generation, and more.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @vaiftechnologies/vaif-client
13
+ # or
14
+ pnpm add @vaiftechnologies/vaif-client
15
+ # or
16
+ yarn add @vaiftechnologies/vaif-client
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```typescript
22
+ import { createClient } from '@vaiftechnologies/vaif-client';
23
+
24
+ const vaif = createClient({
25
+ projectId: 'your-project-id',
26
+ apiKey: 'your-api-key',
27
+ });
28
+
29
+ // Database - fluent query builder
30
+ const { data: users } = await vaif.db
31
+ .from('users')
32
+ .select('id, name, email')
33
+ .eq('active', true)
34
+ .order('created_at', { ascending: false })
35
+ .limit(10)
36
+ .execute();
37
+
38
+ // Realtime - WebSocket subscriptions
39
+ vaif.realtime.connect();
40
+ vaif.realtime.channel('messages')
41
+ .on('postgres_changes', { event: 'INSERT', table: 'messages' }, (payload) => {
42
+ console.log('New message:', payload);
43
+ })
44
+ .subscribe();
45
+
46
+ // Storage - file upload with CDN
47
+ const { data } = await vaif.storage.from('avatars').upload('user.png', file);
48
+
49
+ // Functions - edge function invocation
50
+ const { data: result } = await vaif.functions.invoke('send-email', {
51
+ body: { to: 'user@example.com', subject: 'Hello' },
52
+ });
53
+ ```
54
+
55
+ ## Modules
56
+
57
+ | Module | Description |
58
+ |--------|-------------|
59
+ | `vaif.db` | Database operations with fluent query builder |
60
+ | `vaif.auth` | Authentication (email, OAuth, OTP, MFA) |
61
+ | `vaif.realtime` | WebSocket subscriptions, channels, presence |
62
+ | `vaif.storage` | File storage with CDN and image transforms |
63
+ | `vaif.functions` | Edge function invocation |
64
+ | `vaif.ai` | AI-powered code generation and chat |
65
+ | `vaif.schema` | Database schema management and migrations |
66
+ | `vaif.typegen` | TypeScript type generation from DB schema |
67
+ | `vaif.projects` | Project management |
68
+ | `vaif.apiKeys` | API key management |
69
+ | `vaif.integrations` | Webhooks and event subscriptions |
70
+ | `vaif.admin` | Platform admin endpoints |
71
+
72
+ ## Database
73
+
74
+ ### Query Builder
75
+
76
+ ```typescript
77
+ interface User {
78
+ id: string;
79
+ email: string;
80
+ name: string;
81
+ active: boolean;
82
+ created_at: string;
83
+ }
84
+
85
+ // Select with filters
86
+ const { data, error } = await vaif.db
87
+ .from<User>('users')
88
+ .select('id, name, email')
89
+ .eq('active', true)
90
+ .order('created_at', { ascending: false })
91
+ .limit(10)
92
+ .execute();
93
+
94
+ // Get single record
95
+ const { data: user, error } = await vaif.db
96
+ .from<User>('users')
97
+ .eq('id', 'user-123')
98
+ .single();
99
+
100
+ // Get single or null
101
+ const { data: user } = await vaif.db
102
+ .from<User>('users')
103
+ .eq('email', 'test@example.com')
104
+ .maybeSingle();
105
+
106
+ // Insert
107
+ const { data: newUser } = await vaif.db
108
+ .from<User>('users')
109
+ .insert({ email: 'new@example.com', name: 'New User', active: true })
110
+ .execute();
111
+
112
+ // Upsert (insert or update on conflict)
113
+ const { data } = await vaif.db
114
+ .from<User>('users')
115
+ .insert({ email: 'user@example.com', name: 'Updated' })
116
+ .onConflict('email')
117
+ .doUpdate({ name: 'Updated' })
118
+ .execute();
119
+
120
+ // Update
121
+ const { data: updated } = await vaif.db
122
+ .from<User>('users')
123
+ .update({ name: 'New Name' })
124
+ .eq('id', 'user-123')
125
+ .execute();
126
+
127
+ // Delete
128
+ await vaif.db.from('users').delete().eq('id', 'user-123').execute();
129
+ ```
130
+
131
+ ### Filters
132
+
133
+ ```typescript
134
+ vaif.db.from('posts')
135
+ .eq('status', 'published') // column = value
136
+ .neq('author_id', null) // column != value
137
+ .gt('views', 100) // column > value
138
+ .gte('rating', 4.0) // column >= value
139
+ .lt('price', 50) // column < value
140
+ .lte('stock', 10) // column <= value
141
+ .like('title', '%TypeScript%') // LIKE (case-sensitive)
142
+ .ilike('title', '%typescript%') // ILIKE (case-insensitive)
143
+ .is('deleted_at', null) // IS NULL
144
+ .in('status', ['draft', 'review']) // IN (...)
145
+ .contains('tags', ['js', 'ts']) // @> (array contains)
146
+ .containedBy('tags', ['js', 'ts', 'go']) // <@ (contained by)
147
+ .overlaps('tags', ['js', 'python']) // && (array overlap)
148
+ .textSearch('body', 'search query') // Full-text search
149
+ .not.eq('role', 'admin') // Negate any filter
150
+ .or('status.eq.draft,status.eq.review') // OR conditions
151
+ .order('created_at', { ascending: false, nullsFirst: false })
152
+ .limit(20)
153
+ .offset(40)
154
+ .range(0, 9) // Shorthand for offset + limit
155
+ .count('exact') // Include total count
156
+ .execute();
157
+ ```
158
+
159
+ ### Raw SQL and RPC
160
+
161
+ ```typescript
162
+ // Raw SQL (admin only)
163
+ const { data } = await vaif.db.raw<User>(
164
+ 'SELECT * FROM users WHERE created_at > $1',
165
+ ['2024-01-01']
166
+ );
167
+
168
+ // Stored procedure
169
+ const { data } = await vaif.db.rpc('get_user_stats', { userId: '123' });
170
+ ```
171
+
172
+ ## Authentication
173
+
174
+ ```typescript
175
+ // Sign up
176
+ const { data, error } = await vaif.auth.signUp({
177
+ email: 'user@example.com',
178
+ password: 'secure-password',
179
+ data: { name: 'John' },
180
+ });
181
+
182
+ // Sign in with password
183
+ const { data, error } = await vaif.auth.signInWithPassword({
184
+ email: 'user@example.com',
185
+ password: 'secure-password',
186
+ });
187
+
188
+ // Sign in with OAuth
189
+ const { data } = await vaif.auth.signInWithOAuth({
190
+ provider: 'google',
191
+ redirectTo: 'https://myapp.com/callback',
192
+ scopes: 'email profile',
193
+ });
194
+
195
+ // Sign in with magic link / OTP
196
+ await vaif.auth.signInWithOtp({
197
+ email: 'user@example.com',
198
+ redirectTo: 'https://myapp.com/verify',
199
+ });
200
+
201
+ // Verify OTP
202
+ const { data } = await vaif.auth.verifyOtp({
203
+ email: 'user@example.com',
204
+ token: '123456',
205
+ type: 'magiclink',
206
+ });
207
+
208
+ // Get current user
209
+ const { data: { user } } = await vaif.auth.getUser();
210
+
211
+ // Listen to auth changes
212
+ const { data: { subscription } } = vaif.auth.onAuthStateChange((event, session) => {
213
+ console.log('Auth event:', event, session);
214
+ });
215
+
216
+ // Sign out
217
+ await vaif.auth.signOut();
218
+
219
+ // Refresh session
220
+ await vaif.auth.refreshSession();
221
+
222
+ // Reset password
223
+ await vaif.auth.resetPasswordForEmail({
224
+ email: 'user@example.com',
225
+ redirectTo: 'https://myapp.com/reset',
226
+ });
227
+ ```
228
+
229
+ ## Realtime
230
+
231
+ ```typescript
232
+ // Connect to realtime server
233
+ vaif.realtime.connect();
234
+
235
+ // Subscribe to database changes
236
+ const channel = vaif.realtime.channel('my-channel')
237
+ .on('postgres_changes', {
238
+ event: 'INSERT',
239
+ schema: 'public',
240
+ table: 'messages',
241
+ filter: 'room_id=eq.123',
242
+ }, (payload) => {
243
+ console.log('New message:', payload.new);
244
+ })
245
+ .on('postgres_changes', {
246
+ event: 'UPDATE',
247
+ schema: 'public',
248
+ table: 'messages',
249
+ }, (payload) => {
250
+ console.log('Updated:', payload.new);
251
+ })
252
+ .subscribe();
253
+
254
+ // Broadcast messages
255
+ channel.broadcast('typing', { userId: 'user-123' });
256
+
257
+ // Presence tracking
258
+ channel.track({ userId: 'user-123', status: 'online' });
259
+ const presenceState = channel.getPresenceState();
260
+
261
+ channel.on('presence', { event: 'sync' }, (state) => {
262
+ console.log('Online users:', state);
263
+ });
264
+
265
+ // Cleanup
266
+ channel.unsubscribe();
267
+ vaif.realtime.removeChannel('my-channel');
268
+ vaif.realtime.disconnect();
269
+ ```
270
+
271
+ ## Storage
272
+
273
+ ```typescript
274
+ // Upload file
275
+ const { data, error } = await vaif.storage
276
+ .from('avatars')
277
+ .upload('user-123/avatar.jpg', file, {
278
+ contentType: 'image/jpeg',
279
+ upsert: true,
280
+ cacheControl: '3600',
281
+ metadata: { userId: 'user-123' },
282
+ });
283
+
284
+ // Download file
285
+ const { data: blob } = await vaif.storage
286
+ .from('avatars')
287
+ .download('user-123/avatar.jpg');
288
+
289
+ // Download with image transform
290
+ const { data: thumbnail } = await vaif.storage
291
+ .from('avatars')
292
+ .download('user-123/avatar.jpg', {
293
+ transform: { width: 100, height: 100, resize: 'cover', format: 'webp', quality: 80 },
294
+ });
295
+
296
+ // Get public URL
297
+ const { data: { publicUrl } } = vaif.storage
298
+ .from('avatars')
299
+ .getPublicUrl('user-123/avatar.jpg');
300
+
301
+ // Create signed URL (temporary access)
302
+ const { data } = await vaif.storage
303
+ .from('private')
304
+ .createSignedUrl('document.pdf', { expiresIn: 3600 });
305
+
306
+ // List files
307
+ const { data: files } = await vaif.storage
308
+ .from('avatars')
309
+ .list('user-123/', { limit: 100, sortBy: { column: 'name', order: 'asc' } });
310
+
311
+ // Move/copy/delete
312
+ await vaif.storage.from('avatars').move('old-path.jpg', 'new-path.jpg');
313
+ await vaif.storage.from('avatars').copy('source.jpg', 'dest.jpg');
314
+ await vaif.storage.from('avatars').remove(['old-file.jpg', 'another.jpg']);
315
+
316
+ // Bucket management
317
+ const { data: buckets } = await vaif.storage.listBuckets();
318
+ await vaif.storage.createBucket('documents', {
319
+ public: false,
320
+ fileSizeLimit: 10_000_000,
321
+ allowedMimeTypes: ['application/pdf', 'image/*'],
322
+ });
323
+ await vaif.storage.deleteBucket('old-bucket');
324
+ ```
325
+
326
+ ## Edge Functions
327
+
328
+ ```typescript
329
+ // Invoke a function
330
+ const { data, error } = await vaif.functions.invoke<{ sent: boolean }>('send-email', {
331
+ body: { to: 'user@example.com', subject: 'Hello' },
332
+ headers: { 'x-custom-header': 'value' },
333
+ timeout: 15000,
334
+ });
335
+
336
+ // Get function URL for direct use
337
+ const url = vaif.functions.createUrl('send-email');
338
+
339
+ // List deployed functions
340
+ const { data: functions } = await vaif.functions.list();
341
+
342
+ // Get function details
343
+ const { data: fn } = await vaif.functions.get('send-email');
344
+ ```
345
+
346
+ ## AI Generation
347
+
348
+ ```typescript
349
+ // Generate database schema from natural language
350
+ const { data, error } = await vaif.ai.generateSchema({
351
+ prompt: 'Create a blog with posts, authors, and comments',
352
+ format: 'drizzle',
353
+ includeRelations: true,
354
+ });
355
+
356
+ // Generate edge function
357
+ const { data } = await vaif.ai.generateFunction({
358
+ prompt: 'Create a function that sends welcome emails',
359
+ name: 'send-welcome-email',
360
+ runtime: 'edge',
361
+ });
362
+
363
+ // Generate API endpoint
364
+ const { data } = await vaif.ai.generateEndpoint({
365
+ prompt: 'Get user profile with recent posts',
366
+ method: 'GET',
367
+ path: '/users/:id/profile',
368
+ requiresAuth: true,
369
+ });
370
+
371
+ // AI chat assistant
372
+ const { data } = await vaif.ai.chat({
373
+ messages: [
374
+ { role: 'user', content: 'How do I add pagination to my posts query?' },
375
+ ],
376
+ context: { schema: mySchemaString },
377
+ });
378
+
379
+ // Streaming chat
380
+ for await (const chunk of vaif.ai.chatStream({
381
+ messages: [{ role: 'user', content: 'Explain this schema' }],
382
+ })) {
383
+ process.stdout.write(chunk);
384
+ }
385
+
386
+ // Code review
387
+ const { data } = await vaif.ai.review(code, {
388
+ language: 'typescript',
389
+ focus: ['security', 'performance'],
390
+ });
391
+
392
+ // Generate SQL migration
393
+ const { data } = await vaif.ai.generateMigration({
394
+ currentSchema: oldSchema,
395
+ targetSchema: newSchema,
396
+ database: 'postgresql',
397
+ });
398
+
399
+ // Check AI credits
400
+ const { data: credits } = await vaif.ai.getCredits();
401
+ console.log(`Balance: ${credits.balance} credits`);
402
+ ```
403
+
404
+ ## Configuration
405
+
406
+ ```typescript
407
+ import { createClient } from '@vaiftechnologies/vaif-client';
408
+
409
+ const vaif = createClient({
410
+ // Required
411
+ projectId: 'your-project-id',
412
+ apiKey: 'your-api-key',
413
+
414
+ // API endpoints
415
+ apiUrl: 'https://api.vaif.studio', // Custom API URL
416
+ realtimeUrl: 'wss://realtime.vaif.studio', // Custom WebSocket URL
417
+
418
+ // Request options
419
+ timeout: 30000, // Request timeout (ms)
420
+ headers: { 'x-custom': 'value' }, // Custom headers
421
+
422
+ // Auth
423
+ autoRefreshToken: true, // Auto-refresh JWT
424
+ persistSession: true, // Persist to storage
425
+ storage: customStorageAdapter, // Custom storage
426
+
427
+ // Retry with exponential backoff
428
+ retry: {
429
+ maxRetries: 3, // Max retry attempts
430
+ retryDelay: 1000, // Initial delay (ms)
431
+ maxRetryDelay: 30000, // Max delay (ms)
432
+ backoffMultiplier: 2, // Exponential multiplier
433
+ retryOn: [429, 500, 502, 503, 504], // Status codes to retry
434
+ retryOnNetworkError: true, // Retry on network errors
435
+ },
436
+
437
+ // Interceptors for observability
438
+ interceptors: {
439
+ onRequest: (ctx) => {
440
+ console.log(`${ctx.method} ${ctx.path} (attempt ${ctx.attempt})`);
441
+ return ctx; // optionally modify request
442
+ },
443
+ onResponse: (ctx) => {
444
+ console.log(`${ctx.status} in ${ctx.durationMs}ms`);
445
+ },
446
+ onError: (ctx) => {
447
+ console.error(`Error: ${ctx.error.message}`, ctx.willRetry ? '(retrying)' : '');
448
+ },
449
+ },
450
+
451
+ // Debug
452
+ debug: false,
453
+ });
454
+ ```
455
+
456
+ ## Error Handling
457
+
458
+ ```typescript
459
+ import {
460
+ VaifError,
461
+ VaifAuthError,
462
+ VaifValidationError,
463
+ VaifNetworkError,
464
+ VaifRateLimitError,
465
+ VaifNotFoundError,
466
+ VaifConflictError,
467
+ VaifTimeoutError,
468
+ isVaifError,
469
+ } from '@vaiftechnologies/vaif-client';
470
+
471
+ // All methods return { data, error } - check error first
472
+ const { data, error } = await vaif.db.from('users').eq('id', '123').single();
473
+
474
+ if (error) {
475
+ console.log('Error:', error.message, error.code);
476
+ }
477
+
478
+ // Or use error classes directly
479
+ try {
480
+ // ... operations that throw
481
+ } catch (err) {
482
+ if (err instanceof VaifAuthError) {
483
+ console.log('Auth error:', err.message);
484
+ } else if (err instanceof VaifValidationError) {
485
+ console.log('Validation:', err.fieldErrors);
486
+ } else if (err instanceof VaifRateLimitError) {
487
+ console.log(`Rate limited, retry after ${err.retryAfter}s`);
488
+ } else if (err instanceof VaifNotFoundError) {
489
+ console.log('Not found');
490
+ } else if (err instanceof VaifTimeoutError) {
491
+ console.log(`Timed out after ${err.timeoutMs}ms`);
492
+ } else if (err instanceof VaifNetworkError) {
493
+ console.log('Network error:', err.cause?.message);
494
+ } else if (isVaifError(err)) {
495
+ console.log('VAIF error:', err.code, err.statusCode, err.requestId);
496
+ }
497
+ }
498
+ ```
499
+
500
+ ### Error Hierarchy
501
+
502
+ ```
503
+ VaifError (base)
504
+ ├── VaifAuthError (401/403)
505
+ ├── VaifValidationError (400, with fieldErrors)
506
+ ├── VaifRateLimitError (429, with retryAfter)
507
+ ├── VaifNotFoundError (404)
508
+ ├── VaifConflictError (409)
509
+ └── VaifNetworkError
510
+ └── VaifTimeoutError
511
+ ```
512
+
513
+ ## TypeScript
514
+
515
+ The SDK is fully typed. Use generics for type-safe operations:
516
+
517
+ ```typescript
518
+ interface Post {
519
+ id: string;
520
+ title: string;
521
+ content: string;
522
+ author_id: string;
523
+ published: boolean;
524
+ }
525
+
526
+ // Typed queries
527
+ const { data } = await vaif.db.from<Post>('posts')
528
+ .select('id, title')
529
+ .eq('published', true)
530
+ .execute();
531
+ // data is Post[]
532
+
533
+ // Typed single
534
+ const { data: post } = await vaif.db.from<Post>('posts')
535
+ .eq('id', '123')
536
+ .single();
537
+ // post is Post
538
+
539
+ // Typed functions
540
+ const { data } = await vaif.functions.invoke<{ count: number }>('get-stats');
541
+ // data is { count: number }
542
+ ```
543
+
544
+ ## Related Packages
545
+
546
+ - [@vaiftech/client](https://www.npmjs.com/package/@vaiftech/client) - Monorepo client (internal)
547
+ - [@vaiftech/auth](https://www.npmjs.com/package/@vaiftech/auth) - Standalone auth client
548
+ - [@vaiftech/react](https://www.npmjs.com/package/@vaiftech/react) - React hooks
549
+ - [@vaiftech/sdk-expo](https://www.npmjs.com/package/@vaiftech/sdk-expo) - React Native/Expo SDK
550
+ - [vaif-client (PyPI)](https://pypi.org/project/vaif-client/) - Python SDK
551
+
552
+ ## License
553
+
554
+ MIT