@taruvi/sdk 1.0.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.
Files changed (42) hide show
  1. package/.claude/settings.local.json +16 -0
  2. package/DATAPROVIDER_CONTEXT.md +828 -0
  3. package/README.md +703 -0
  4. package/USAGE_EXAMPLE.md +86 -0
  5. package/package.json +25 -0
  6. package/src/client.ts +81 -0
  7. package/src/index.ts +20 -0
  8. package/src/lib/Database/DatabaseClient.ts +87 -0
  9. package/src/lib/Database/types.ts +29 -0
  10. package/src/lib/Function/FunctionsClient.ts +27 -0
  11. package/src/lib/Function/types.ts +17 -0
  12. package/src/lib/Secrets/SecretsClient.ts +44 -0
  13. package/src/lib/Secrets/types.ts +17 -0
  14. package/src/lib/Settings/SettingsClient.ts +14 -0
  15. package/src/lib/Settings/types.ts +4 -0
  16. package/src/lib/Storage/StorageClient.ts +88 -0
  17. package/src/lib/Storage/types.ts +40 -0
  18. package/src/lib/auth/AuthClient.ts +64 -0
  19. package/src/lib/auth/types.ts +9 -0
  20. package/src/lib/user/UserClient.ts +44 -0
  21. package/src/lib/user/types.ts +69 -0
  22. package/src/lib-internal/errors/ErrorClient.ts +12 -0
  23. package/src/lib-internal/errors/index.ts +25 -0
  24. package/src/lib-internal/errors/types.ts +105 -0
  25. package/src/lib-internal/http/HttpClient.ts +96 -0
  26. package/src/lib-internal/http/types.ts +10 -0
  27. package/src/lib-internal/routes/AuthRoutes.ts +0 -0
  28. package/src/lib-internal/routes/DatabaseRoutes.ts +5 -0
  29. package/src/lib-internal/routes/FunctionRoutes.ts +3 -0
  30. package/src/lib-internal/routes/RouteBuilder.ts +0 -0
  31. package/src/lib-internal/routes/SecretsRoutes.ts +5 -0
  32. package/src/lib-internal/routes/SettingsRoutes.ts +3 -0
  33. package/src/lib-internal/routes/StorageRoutes.ts +7 -0
  34. package/src/lib-internal/routes/UserRoutes.ts +9 -0
  35. package/src/lib-internal/routes/index.ts +0 -0
  36. package/src/lib-internal/token/TokenClient.ts +30 -0
  37. package/src/lib-internal/token/types.ts +0 -0
  38. package/src/types.ts +68 -0
  39. package/src/utils/enums.ts +12 -0
  40. package/src/utils/utils.ts +36 -0
  41. package/tests/mocks/db.json +1 -0
  42. package/tsconfig.json +43 -0
@@ -0,0 +1,828 @@
1
+ # Taruvi SDK - Complete Codebase Reference for Data Provider Generation
2
+
3
+ ## Project Overview
4
+
5
+ **Taruvi SDK** (`@taruvi-io/sdk`) is a TypeScript SDK for the Taruvi Data Service - a PostgREST-like dynamic API system that provides:
6
+ - Dynamic database table creation and management
7
+ - File storage with bucket-based organization
8
+ - Serverless function execution
9
+ - Multi-tenant architecture with app isolation
10
+ - Rich querying with 32+ filter operators (Refine.dev compatible)
11
+ - JWT-based authentication
12
+
13
+ ---
14
+
15
+ ## Architecture Principles
16
+
17
+ 1. **Dependency Injection** - No singletons; services receive `Client` instance
18
+ 2. **Two-Tier API** - Public (`lib/`) vs Internal (`lib-internal/`)
19
+ 3. **Query Builder Pattern** - Chainable, fluent APIs with deferred execution
20
+ 4. **Type Safety** - Full TypeScript with strict mode
21
+ 5. **Tree-Shakeable** - Modular exports for bundle optimization
22
+
23
+ ---
24
+
25
+ ## Directory Structure
26
+
27
+ ```
28
+ src/
29
+ ├── client.ts # Main Client orchestrator
30
+ ├── index.ts # Public exports
31
+ ├── types.ts # Core config + filter types
32
+
33
+ ├── lib/ # PUBLIC API
34
+ │ ├── auth/AuthClient.ts
35
+ │ ├── user/UserClient.ts
36
+ │ ├── Storage/StorageClient.ts
37
+ │ ├── Database/DatabaseClient.ts
38
+ │ ├── Function/FunctionsClient.ts
39
+ │ ├── Settings/SettingsClient.ts
40
+ │ └── Secrets/SecretsClient.ts
41
+
42
+ ├── lib-internal/ # INTERNAL API
43
+ │ ├── http/HttpClient.ts
44
+ │ ├── token/TokenClient.ts
45
+ │ ├── routes/*.ts
46
+ │ └── errors/types.ts
47
+
48
+ └── utils/
49
+ ├── utils.ts # Runtime detection, buildQueryString
50
+ └── enums.ts # MimeTypeCategory, Visibility
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Core Configuration
56
+
57
+ ```typescript
58
+ interface TaruviConfig {
59
+ apiKey: string // Site/organization identifier
60
+ appSlug: string // App identifier (multi-tenant)
61
+ baseUrl: string // API endpoint (e.g., https://test-api.taruvi.cloud)
62
+ token?: string // Optional pre-existing JWT token
63
+ }
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Client Initialization
69
+
70
+ ```typescript
71
+ import { Client, Database, Storage, User, Auth, Functions, Secrets } from '@taruvi-io/sdk'
72
+
73
+ const client = new Client({
74
+ apiKey: 'your-site-api-key',
75
+ appSlug: 'my-app',
76
+ baseUrl: 'https://test-api.taruvi.cloud'
77
+ })
78
+
79
+ // Services are instantiated with the client
80
+ const db = new Database(client, {})
81
+ const storage = new Storage(client, {})
82
+ const user = new User(client)
83
+ const auth = new Auth(client)
84
+ const functions = new Functions(client)
85
+ ```
86
+
87
+ ---
88
+
89
+ ## HTTP Client (Internal)
90
+
91
+ ```typescript
92
+ class HttpClient {
93
+ constructor(config: TaruviConfig, tokenClient: TokenClient)
94
+
95
+ // Authentication headers:
96
+ // - Token {apiKey} (developer auth)
97
+ // - Bearer {jwt} (user auth - takes precedence)
98
+
99
+ async get<T>(endpoint: string): Promise<T>
100
+ async post<T, D>(endpoint: string, body: D): Promise<T>
101
+ async put<T, D>(endpoint: string, body: D): Promise<T>
102
+ async patch<T, D>(endpoint: string, body: D): Promise<T>
103
+ async delete<T, D>(endpoint: string, body?: D): Promise<T>
104
+ }
105
+ ```
106
+
107
+ ---
108
+
109
+ ## API Endpoints
110
+
111
+ ### Database Routes
112
+ ```
113
+ GET /api/apps/{appSlug}/datatables/{tableName}/data/ # List records
114
+ GET /api/apps/{appSlug}/datatables/{tableName}/data/{id}/ # Get record
115
+ POST /api/apps/{appSlug}/datatables/{tableName}/data/ # Create record
116
+ PATCH /api/apps/{appSlug}/datatables/{tableName}/data/{id}/ # Update record
117
+ DELETE /api/apps/{appSlug}/datatables/{tableName}/data/{id}/ # Delete record
118
+ ```
119
+
120
+ ### Storage Routes
121
+ ```
122
+ GET /api/apps/{appSlug}/storage/buckets/{bucket}/objects/ # List files
123
+ GET /api/apps/{appSlug}/storage/buckets/{bucket}/objects/{path}/ # Get file
124
+ POST /api/apps/{appSlug}/storage/buckets/{bucket}/objects/batch-upload # Upload
125
+ POST /api/apps/{appSlug}/storage/buckets/{bucket}/objects/batch-delete # Delete
126
+ PUT /api/apps/{appSlug}/storage/buckets/{bucket}/objects/{path}/ # Update metadata
127
+ ```
128
+
129
+ ### User Routes
130
+ ```
131
+ GET /api/users/ # List users
132
+ GET /api/users/me/ # Current user
133
+ POST /api/users/ # Create user
134
+ PUT /api/users/{username}/ # Update user
135
+ DELETE /api/users/{username}/ # Delete user
136
+ ```
137
+
138
+ ### Function Routes
139
+ ```
140
+ POST /api/functions/apps/{appSlug}/functions/{functionSlug}/execute/
141
+ ```
142
+
143
+ ### Settings Routes
144
+ ```
145
+ GET /api/settings/metadata/
146
+ ```
147
+
148
+ ### Secrets Routes
149
+ ```
150
+ GET /api/secrets/
151
+ GET /api/secrets/{key}/
152
+ PUT /api/secrets/{key}/
153
+ ```
154
+
155
+ ---
156
+
157
+ ## Query Parameters (Refine.dev Compatible)
158
+
159
+ ### Pagination
160
+ - `_start=0` / `_end=10` (offset-based)
161
+ - `page=1` / `pageSize=20` (DRF style)
162
+ - `limit=10` / `offset=0`
163
+
164
+ ### Sorting
165
+ - `_sort=created_at,name`
166
+ - `_order=DESC,ASC`
167
+ - `ordering=-created_at` (DRF style: `-` prefix for DESC)
168
+
169
+ ### Filtering (32+ Operators)
170
+ ```
171
+ # Exact match
172
+ status=active
173
+
174
+ # Comparison
175
+ age_gte=18 # >=
176
+ age_gt=18 # >
177
+ age_lte=65 # <=
178
+ age_lt=65 # <
179
+ age_between=18,65 # range
180
+
181
+ # String operations
182
+ name_contains=john
183
+ name_startswith=J
184
+ name_endswith=son
185
+ name_icontains=john # case-insensitive
186
+
187
+ # Array operations
188
+ status_in=active,pending
189
+ tags_nin=deleted
190
+
191
+ # Null checks
192
+ deleted_at_null=true
193
+ email_nnull=true
194
+
195
+ # Foreign key population
196
+ populate=* # All relations
197
+ populate=user_id,org_id # Specific relations
198
+ ```
199
+
200
+ ### Storage-Specific Filters
201
+ ```typescript
202
+ interface StorageFilters {
203
+ page?: number
204
+ pageSize?: number
205
+
206
+ // Size filters (bytes)
207
+ size__gte?: number
208
+ size__lte?: number
209
+ min_size?: number
210
+ max_size?: number
211
+
212
+ // Date filters (ISO 8601)
213
+ created_at__gte?: string
214
+ created_at__lte?: string
215
+ created_after?: string
216
+ created_before?: string
217
+
218
+ // Search
219
+ search?: string
220
+ filename__icontains?: string
221
+ prefix?: string
222
+
223
+ // MIME type
224
+ mimetype?: string
225
+ mimetype__in?: string
226
+ mimetype_category?: 'image' | 'video' | 'audio' | 'application' | 'text'
227
+
228
+ // Visibility
229
+ visibility?: 'public' | 'private'
230
+ created_by_me?: boolean
231
+
232
+ // Sorting
233
+ ordering?: string
234
+ }
235
+ ```
236
+
237
+ ### Database Filters
238
+ ```typescript
239
+ interface DatabaseFilters {
240
+ page?: number
241
+ pageSize?: number
242
+ ordering?: string // "-field" for DESC, "field" for ASC
243
+
244
+ // Dynamic filters - any field with operators
245
+ [key: string]: string | number | boolean | undefined
246
+ }
247
+ ```
248
+
249
+ ---
250
+
251
+ ## Data Types
252
+
253
+ ### User Types
254
+ ```typescript
255
+ interface UserCreateRequest {
256
+ username: string
257
+ email: string
258
+ password: string
259
+ confirm_password: string
260
+ first_name: string
261
+ last_name: string
262
+ is_active: boolean
263
+ is_staff: boolean
264
+ attributes: string
265
+ }
266
+
267
+ interface UserDataResponse {
268
+ id: number
269
+ username: string
270
+ email: string
271
+ first_name: string
272
+ last_name: string
273
+ full_name: string
274
+ is_active: boolean
275
+ is_staff: boolean
276
+ is_deleted: boolean
277
+ date_joined: string // ISO 8601
278
+ last_login: string
279
+ attributes: string
280
+ }
281
+
282
+ interface UserUpdateRequest {
283
+ username?: string
284
+ email?: string
285
+ password?: string
286
+ confirm_password?: string
287
+ first_name?: string
288
+ last_name?: string
289
+ is_active?: boolean
290
+ is_staff?: boolean
291
+ attributes?: string
292
+ }
293
+
294
+ interface UserList {
295
+ search: string
296
+ is_active: boolean
297
+ is_staff: boolean
298
+ is_superuser: boolean
299
+ is_deleted: boolean
300
+ ordering: string
301
+ page: Number
302
+ page_size: Number
303
+ }
304
+ ```
305
+
306
+ ### Storage Types
307
+ ```typescript
308
+ interface StorageRequest {
309
+ files: File[]
310
+ paths: string[]
311
+ metadatas: object[]
312
+ }
313
+
314
+ interface StorageUpdateRequest {
315
+ metadata?: Record<string, unknown>
316
+ visibility?: 'public' | 'private'
317
+ }
318
+
319
+ interface StorageResponse {
320
+ id: number
321
+ uuid: string
322
+ filename: string
323
+ file_path: string
324
+ file_url: string
325
+ size: number
326
+ mimetype: string
327
+ metadata?: Record<string, unknown>
328
+ visibility?: string
329
+ created_at: string
330
+ updated_at: string
331
+ }
332
+ ```
333
+
334
+ ### Database Types
335
+ ```typescript
336
+ interface DatabaseRequest {
337
+ [key: string]: unknown
338
+ }
339
+
340
+ interface DatabaseResponse<T = unknown> {
341
+ id?: string | number
342
+ created_at?: string
343
+ updated_at?: string
344
+ [key: string]: T | string | number | undefined
345
+ }
346
+ ```
347
+
348
+ ### Function Types
349
+ ```typescript
350
+ interface FunctionRequest {
351
+ async?: boolean
352
+ params?: Record<string, unknown>
353
+ }
354
+
355
+ interface FunctionInvocation {
356
+ invocation_id: number
357
+ celery_task_id: string
358
+ status: string
359
+ created_at: string
360
+ updated_at: string
361
+ }
362
+
363
+ interface FunctionResponse<T = unknown> {
364
+ data: T | null
365
+ invocation: FunctionInvocation
366
+ }
367
+ ```
368
+
369
+ ### Secret Types
370
+ ```typescript
371
+ interface SecretRequest {
372
+ value: string
373
+ }
374
+
375
+ interface SecretResponse {
376
+ key: string
377
+ value: string
378
+ created_at?: string
379
+ updated_at?: string
380
+ }
381
+ ```
382
+
383
+ ---
384
+
385
+ ## Current Service Implementations
386
+
387
+ ### Database (Query Builder Pattern)
388
+ ```typescript
389
+ class Database {
390
+ constructor(client: Client, urlParams: UrlParams, operation?: HttpMethod, body?: object, filters?: DatabaseFilters)
391
+
392
+ from(tableName: string): Database
393
+ filter(filters: DatabaseFilters): Database
394
+ get(recordId: string): Database
395
+ update(body: any): Database
396
+ delete(recordId?: string): Database
397
+ execute(): Promise<T>
398
+ }
399
+
400
+ // Usage
401
+ const records = await db
402
+ .from('users')
403
+ .filter({ status: 'active', age_gte: 18 })
404
+ .execute()
405
+
406
+ const record = await db
407
+ .from('users')
408
+ .get('123')
409
+ .execute()
410
+
411
+ await db
412
+ .from('users')
413
+ .get('123')
414
+ .update({ status: 'inactive' })
415
+ .execute()
416
+ ```
417
+
418
+ ### Storage (Query Builder Pattern)
419
+ ```typescript
420
+ class Storage {
421
+ constructor(client: Client, urlParams: BucketUrlParams, operation?: HttpMethod, body?: object, filters?: StorageFilters)
422
+
423
+ from(bucket: string): Storage
424
+ filter(filters: StorageFilters): Storage
425
+ download(path: string): Storage
426
+ upload(filesData: { files: File[], paths: string[], metadatas: object[] }): Storage
427
+ update(path: string, body: object): Storage
428
+ delete(path: string): Storage
429
+ execute(): Promise<T>
430
+ }
431
+
432
+ // Usage
433
+ const files = await storage
434
+ .from('uploads')
435
+ .filter({ mimetype_category: 'image', size__lte: 5000000 })
436
+ .execute()
437
+
438
+ await storage
439
+ .from('uploads')
440
+ .upload({ files: [file], paths: ['images/photo.jpg'], metadatas: [{ alt: 'Photo' }] })
441
+ .execute()
442
+ ```
443
+
444
+ ### User (Direct Methods)
445
+ ```typescript
446
+ class User {
447
+ constructor(client: Client)
448
+
449
+ getUserData(): Promise<UserDataResponse>
450
+ createUser(userData: UserCreateRequest): Promise<UserCreateResponse>
451
+ updateUser(username: string, body: UserUpdateRequest): Promise<UserCreateResponse>
452
+ deleteUser(username: string): Promise<void>
453
+ list(filters: UserList): Promise<any>
454
+ }
455
+
456
+ // Usage
457
+ const currentUser = await user.getUserData()
458
+ const users = await user.list({ is_active: true, page: 1, page_size: 20 })
459
+ ```
460
+
461
+ ### Auth
462
+ ```typescript
463
+ class Auth {
464
+ constructor(client: Client)
465
+
466
+ authenticateUser(): Promise<void> // Stores JWT in localStorage
467
+ isUserAuthenticated(): Promise<boolean>
468
+ redirectToLogin(): Promise<void>
469
+ }
470
+ ```
471
+
472
+ ### Functions
473
+ ```typescript
474
+ class Functions {
475
+ constructor(client: Client)
476
+
477
+ execute<T>(functionSlug: string, options?: FunctionRequest): Promise<FunctionResponse<T>>
478
+ }
479
+
480
+ // Usage
481
+ const result = await functions.execute<{ sum: number }>('calculate', {
482
+ async: false,
483
+ params: { a: 1, b: 2 }
484
+ })
485
+ ```
486
+
487
+ ### Settings
488
+ ```typescript
489
+ class Settings {
490
+ constructor(client: Client)
491
+
492
+ get<T>(): Promise<T>
493
+ }
494
+
495
+ // Usage
496
+ const config = await settings.get<{ theme: string, features: string[] }>()
497
+ ```
498
+
499
+ ### Secrets (Query Builder Pattern)
500
+ ```typescript
501
+ class Secrets {
502
+ constructor(client: Client, urlParams?: SecretsUrlParams, body?: object, method?: HttpMethod)
503
+
504
+ list(): Secrets
505
+ get(key: string): Secrets
506
+ update(key: string, body: object): Secrets
507
+ execute<T>(): Promise<T>
508
+ }
509
+
510
+ // Usage
511
+ const allSecrets = await secrets.list().execute()
512
+ const apiKey = await secrets.get('API_KEY').execute()
513
+ await secrets.update('API_KEY', { value: 'new-key' }).execute()
514
+ ```
515
+
516
+ ---
517
+
518
+ ## Route Definitions
519
+
520
+ ### DatabaseRoutes
521
+ ```typescript
522
+ const DatabaseRoutes = {
523
+ baseUrl: (appSlug: string) => `api/apps/${appSlug}`,
524
+ dataTables: (tableName: string): string => `/datatables/${tableName}/data`,
525
+ recordId: (recordId: string): string => `/${recordId}`
526
+ }
527
+ ```
528
+
529
+ ### StorageRoutes
530
+ ```typescript
531
+ const StorageRoutes = {
532
+ baseUrl: (appslug: string, bucket: string) => `api/apps/${appslug}/storage/buckets/${bucket}/objects`,
533
+ path: (path: string) => "/" + path,
534
+ upload: () => "/batch-upload",
535
+ delete: () => "/batch-delete"
536
+ }
537
+ ```
538
+
539
+ ### UserRoutes
540
+ ```typescript
541
+ const UserRoutes = {
542
+ baseUrl: "api/users/",
543
+ getCurrentUser: () => `${UserRoutes.baseUrl}me/`,
544
+ updateUser: (username: string) => `${UserRoutes.baseUrl}${username}/`,
545
+ deleteUser: (username: string) => `${UserRoutes.baseUrl}${username}/`,
546
+ listUser: (filter: string) => `${UserRoutes.baseUrl}${filter}`
547
+ }
548
+ ```
549
+
550
+ ### FunctionRoutes
551
+ ```typescript
552
+ const FunctionRoutes = {
553
+ baseUrl: (appSlug: string, functionSlug: string) => `/api/functions/apps/${appSlug}/functions/${functionSlug}`
554
+ }
555
+ ```
556
+
557
+ ### SettingsRoutes
558
+ ```typescript
559
+ const SettingsRoutes = {
560
+ metadata: "api/settings/metadata/"
561
+ }
562
+ ```
563
+
564
+ ### SecretsRoutes
565
+ ```typescript
566
+ const SecretsRoutes = {
567
+ baseUrl: "api/secrets/",
568
+ get: (key: string) => `api/secrets/${key}/`,
569
+ update: (key: string) => `api/secrets/${key}/`
570
+ }
571
+ ```
572
+
573
+ ---
574
+
575
+ ## Error Codes
576
+
577
+ ```typescript
578
+ enum ErrorCode {
579
+ // General errors (1000-1099)
580
+ UNKNOWN_ERROR = 'UNKNOWN_ERROR',
581
+ INTERNAL_ERROR = 'INTERNAL_ERROR',
582
+ TIMEOUT_ERROR = 'TIMEOUT_ERROR',
583
+
584
+ // Network errors (1100-1199)
585
+ NETWORK_ERROR = 'NETWORK_ERROR',
586
+ CONNECTION_ERROR = 'CONNECTION_ERROR',
587
+ REQUEST_FAILED = 'REQUEST_FAILED',
588
+
589
+ // Authentication errors (1200-1299)
590
+ AUTH_ERROR = 'AUTH_ERROR',
591
+ UNAUTHORIZED = 'UNAUTHORIZED',
592
+ TOKEN_EXPIRED = 'TOKEN_EXPIRED',
593
+ TOKEN_INVALID = 'TOKEN_INVALID',
594
+ SESSION_EXPIRED = 'SESSION_EXPIRED',
595
+ INVALID_CREDENTIALS = 'INVALID_CREDENTIALS',
596
+
597
+ // Authorization errors (1300-1399)
598
+ FORBIDDEN = 'FORBIDDEN',
599
+ INSUFFICIENT_PERMISSIONS = 'INSUFFICIENT_PERMISSIONS',
600
+
601
+ // Validation errors (1400-1499)
602
+ VALIDATION_ERROR = 'VALIDATION_ERROR',
603
+ INVALID_INPUT = 'INVALID_INPUT',
604
+ MISSING_REQUIRED_FIELD = 'MISSING_REQUIRED_FIELD',
605
+ INVALID_FORMAT = 'INVALID_FORMAT',
606
+
607
+ // Database errors (1500-1599)
608
+ DATABASE_ERROR = 'DATABASE_ERROR',
609
+ QUERY_FAILED = 'QUERY_FAILED',
610
+ RECORD_NOT_FOUND = 'RECORD_NOT_FOUND',
611
+ DUPLICATE_ENTRY = 'DUPLICATE_ENTRY',
612
+ CONSTRAINT_VIOLATION = 'CONSTRAINT_VIOLATION',
613
+
614
+ // Storage errors (1600-1699)
615
+ STORAGE_ERROR = 'STORAGE_ERROR',
616
+ FILE_NOT_FOUND = 'FILE_NOT_FOUND',
617
+ FILE_TOO_LARGE = 'FILE_TOO_LARGE',
618
+ INVALID_FILE_TYPE = 'INVALID_FILE_TYPE',
619
+ UPLOAD_FAILED = 'UPLOAD_FAILED',
620
+ DOWNLOAD_FAILED = 'DOWNLOAD_FAILED',
621
+
622
+ // Function errors (1700-1799)
623
+ FUNCTION_ERROR = 'FUNCTION_ERROR',
624
+ FUNCTION_NOT_FOUND = 'FUNCTION_NOT_FOUND',
625
+ FUNCTION_EXECUTION_FAILED = 'FUNCTION_EXECUTION_FAILED',
626
+ FUNCTION_TIMEOUT = 'FUNCTION_TIMEOUT',
627
+
628
+ // Rate limiting errors (1800-1899)
629
+ RATE_LIMIT_EXCEEDED = 'RATE_LIMIT_EXCEEDED',
630
+ QUOTA_EXCEEDED = 'QUOTA_EXCEEDED',
631
+
632
+ // Client errors (1900-1999)
633
+ CONFIGURATION_ERROR = 'CONFIGURATION_ERROR',
634
+ INVALID_API_KEY = 'INVALID_API_KEY',
635
+ INVALID_CONFIG = 'INVALID_CONFIG'
636
+ }
637
+
638
+ enum ErrorSeverity {
639
+ LOW = 'low',
640
+ MEDIUM = 'medium',
641
+ HIGH = 'high',
642
+ CRITICAL = 'critical'
643
+ }
644
+
645
+ interface ErrorResponse {
646
+ code: ErrorCode
647
+ message: string
648
+ severity: ErrorSeverity
649
+ timestamp: string
650
+ requestId?: string
651
+ metadata?: Record<string, any>
652
+ cause?: Error
653
+ }
654
+ ```
655
+
656
+ ---
657
+
658
+ ## API Response Format
659
+
660
+ ### List Response
661
+ ```json
662
+ {
663
+ "data": [
664
+ {
665
+ "id": 1,
666
+ "name": "John Doe",
667
+ "age": 30,
668
+ "user_id": 5,
669
+ "user": {
670
+ "id": 5,
671
+ "name": "Admin User",
672
+ "email": "admin@example.com"
673
+ }
674
+ }
675
+ ],
676
+ "total": 156,
677
+ "meta": {
678
+ "offset": 0,
679
+ "count": 10,
680
+ "has_more": true
681
+ }
682
+ }
683
+ ```
684
+
685
+ ### Single Record Response
686
+ ```json
687
+ {
688
+ "id": 1,
689
+ "name": "John Doe",
690
+ "email": "john@example.com",
691
+ "created_at": "2024-01-15T10:30:00Z",
692
+ "updated_at": "2024-01-15T10:30:00Z"
693
+ }
694
+ ```
695
+
696
+ ### Error Response
697
+ ```json
698
+ {
699
+ "error": "Insert failed",
700
+ "detail": "Validation errors: age: must be >= 0"
701
+ }
702
+ ```
703
+
704
+ ---
705
+
706
+ ## Utility Functions
707
+
708
+ ```typescript
709
+ // Query string builder
710
+ function buildQueryString(filters: Record<string, unknown> | undefined): string {
711
+ if (!filters || Object.keys(filters).length === 0) {
712
+ return ''
713
+ }
714
+ const params = new URLSearchParams()
715
+ Object.entries(filters).forEach(([key, value]) => {
716
+ if (value !== undefined && value !== null) {
717
+ params.append(key, String(value))
718
+ }
719
+ })
720
+ const queryString = params.toString()
721
+ return queryString ? `?${queryString}` : ''
722
+ }
723
+
724
+ // Runtime detection
725
+ function isBrowser(): boolean
726
+ function isReactNative(): boolean
727
+ function getRuntimeEnvironment(): 'Browser' | 'ReactNative' | 'Server'
728
+ ```
729
+
730
+ ---
731
+
732
+ ## Enums
733
+
734
+ ```typescript
735
+ enum MimeTypeCategory {
736
+ IMAGE = 'image',
737
+ VIDEO = 'video',
738
+ AUDIO = 'audio',
739
+ APPLICATION = 'application',
740
+ TEXT = 'text'
741
+ }
742
+
743
+ enum Visibility {
744
+ PUBLIC = 'public',
745
+ PRIVATE = 'private'
746
+ }
747
+
748
+ enum HttpMethod {
749
+ GET = 'GET',
750
+ POST = 'POST',
751
+ PUT = 'PUT',
752
+ PATCH = 'PATCH',
753
+ DELETE = 'DELETE'
754
+ }
755
+ ```
756
+
757
+ ---
758
+
759
+ ## Key Design Patterns for Data Providers
760
+
761
+ 1. **Query Builder Pattern**: Chainable methods returning new instances (immutable)
762
+ ```typescript
763
+ from(resource) -> filter(conditions) -> execute()
764
+ ```
765
+
766
+ 2. **Deferred Execution**: Operations are queued, executed on `.execute()`
767
+
768
+ 3. **Route Builders**: Centralized endpoint construction with template functions
769
+
770
+ 4. **Filter Objects**: DRF-style query parameters with operators (`field_operator=value`)
771
+
772
+ 5. **Generic Types**: `<T>` for response typing
773
+
774
+ 6. **HTTP Method Enum**: Type-safe operation selection
775
+
776
+ 7. **Dependency Injection**: All services receive `Client` instance
777
+
778
+ ---
779
+
780
+ ## Implementation Status
781
+
782
+ | Service | Status | Completion | Notes |
783
+ |---------|--------|------------|-------|
784
+ | Client/HTTP | Complete | 90% | Core infrastructure working |
785
+ | User | Functional | 80% | CRUD operations implemented |
786
+ | Auth | Partial | 60% | Basic auth, SSO planned |
787
+ | Storage | Partial | 70% | Query builder working |
788
+ | Database | Planned | 0% | Query builder structure defined |
789
+ | Functions | Complete | 100% | Function execution working |
790
+ | Secrets | Complete | 100% | CRUD operations for secrets |
791
+ | Settings | Functional | 70% | Site config fetching works |
792
+
793
+ ---
794
+
795
+ ## Dependencies
796
+
797
+ **Peer Dependencies:**
798
+ - `axios`: ^1.0.0
799
+ - `@types/node`: ^18.0.0 || ^20.0.0 || ^22.0.0
800
+ - `mime-db`: ^1.54.0
801
+
802
+ **Dev Dependencies:**
803
+ - `typescript`: ^5.7.3
804
+
805
+ ---
806
+
807
+ ## Token Management
808
+
809
+ The SDK uses localStorage for JWT token storage in browser environments:
810
+
811
+ ```typescript
812
+ class TokenClient {
813
+ getToken(): string | null {
814
+ if (isBrowser()) {
815
+ return localStorage.getItem("jwt")
816
+ }
817
+ return null
818
+ }
819
+ }
820
+ ```
821
+
822
+ Authentication headers are automatically applied:
823
+ - API Key: `Authorization: Token {apiKey}` (developer auth)
824
+ - JWT: `Authorization: Bearer {jwt}` (user auth - takes precedence)
825
+
826
+ ---
827
+
828
+ This reference document provides all necessary context for generating refined data providers that align with the Taruvi SDK's architecture, patterns, and API specifications.