@taruvi/sdk 1.0.2 → 1.0.4
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/AI_IMPLEMENTATION_GUIDE.md +733 -0
- package/package.json +1 -1
- package/src/client.ts +32 -6
- package/src/index.ts +2 -1
- package/src/lib/Database/DatabaseClient.ts +16 -7
- package/src/lib/Storage/StorageClient.ts +24 -9
- package/src/lib/auth/AuthClient.ts +201 -48
- package/src/lib-internal/routes/DatabaseRoutes.ts +5 -1
- package/src/lib-internal/routes/StorageRoutes.ts +9 -1
- package/src/lib-internal/token/TokenClient.ts +249 -13
- package/src/lib-internal/routes/RouteBuilder.ts +0 -0
|
@@ -0,0 +1,733 @@
|
|
|
1
|
+
# Taruvi SDK - AI Implementation Guide
|
|
2
|
+
|
|
3
|
+
> Quick reference for implementing Taruvi SDK features with copy-paste examples from production code
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @taruvi-io/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Core Setup
|
|
12
|
+
|
|
13
|
+
### 1. Initialize Client
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { Client } from '@taruvi-io/sdk'
|
|
17
|
+
|
|
18
|
+
const taruviClient = new Client({
|
|
19
|
+
apiKey: "your-site-api-key",
|
|
20
|
+
appSlug: "your-app-slug",
|
|
21
|
+
baseUrl: "https://taruvi-site.taruvi.cloud"
|
|
22
|
+
})
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### 2. Pass to Components (React)
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
// App.tsx
|
|
29
|
+
<Route path="/page" element={<MyPage taruviClient={taruviClient} />} />
|
|
30
|
+
|
|
31
|
+
// MyPage.tsx
|
|
32
|
+
interface MyPageProps {
|
|
33
|
+
taruviClient: Client;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default function MyPage({ taruviClient }: MyPageProps) {
|
|
37
|
+
// Use SDK here
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Auth Service
|
|
44
|
+
|
|
45
|
+
### Check Authentication
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { Auth } from '@taruvi-io/sdk'
|
|
49
|
+
|
|
50
|
+
const auth = new Auth(taruviClient)
|
|
51
|
+
const isAuthenticated = await auth.isUserAuthenticated() // Returns boolean
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Login Flow
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { useEffect } from "react"
|
|
58
|
+
import { Auth } from '@taruvi-io/sdk'
|
|
59
|
+
|
|
60
|
+
export default function Login({ taruviClient }) {
|
|
61
|
+
const auth = new Auth(taruviClient)
|
|
62
|
+
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
const checkAuthAndRedirect = async () => {
|
|
65
|
+
const isAuthenticated = await auth.isUserAuthenticated()
|
|
66
|
+
|
|
67
|
+
if (isAuthenticated) {
|
|
68
|
+
window.location.href = "/dashboard"
|
|
69
|
+
} else {
|
|
70
|
+
await auth.authenticateUser()
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
checkAuthAndRedirect()
|
|
75
|
+
}, [])
|
|
76
|
+
|
|
77
|
+
return <div>Checking authentication...</div>
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## User Service
|
|
84
|
+
|
|
85
|
+
### Get Current User
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { User } from '@taruvi-io/sdk'
|
|
89
|
+
|
|
90
|
+
const user = new User(taruviClient)
|
|
91
|
+
const userData = await user.getUserData()
|
|
92
|
+
|
|
93
|
+
console.log(userData.data.username)
|
|
94
|
+
console.log(userData.data.email)
|
|
95
|
+
console.log(userData.data.full_name)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Create User (Registration)
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { User } from '@taruvi-io/sdk'
|
|
102
|
+
|
|
103
|
+
const user = new User(taruviClient)
|
|
104
|
+
|
|
105
|
+
const newUser = await user.createUser({
|
|
106
|
+
username: "john_doe",
|
|
107
|
+
email: "john@example.com",
|
|
108
|
+
password: "secure123",
|
|
109
|
+
confirm_password: "secure123",
|
|
110
|
+
first_name: "John",
|
|
111
|
+
last_name: "Doe",
|
|
112
|
+
is_active: true,
|
|
113
|
+
is_staff: false,
|
|
114
|
+
attributes: ""
|
|
115
|
+
})
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Update User
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
const user = new User(taruviClient)
|
|
122
|
+
|
|
123
|
+
await user.updateUser("john_doe", {
|
|
124
|
+
email: "newemail@example.com",
|
|
125
|
+
first_name: "Johnny"
|
|
126
|
+
})
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Delete User
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
const user = new User(taruviClient)
|
|
133
|
+
await user.deleteUser("john_doe")
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Complete Registration Form Example
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
import { useState } from "react"
|
|
140
|
+
import { User } from "@taruvi-io/sdk"
|
|
141
|
+
import { useNavigate } from "react-router"
|
|
142
|
+
|
|
143
|
+
export default function Register({ taruviClient }) {
|
|
144
|
+
const navigate = useNavigate()
|
|
145
|
+
const [formData, setFormData] = useState({
|
|
146
|
+
username: "",
|
|
147
|
+
email: "",
|
|
148
|
+
password: "",
|
|
149
|
+
confirm_password: "",
|
|
150
|
+
first_name: "",
|
|
151
|
+
last_name: "",
|
|
152
|
+
is_active: true,
|
|
153
|
+
is_staff: false
|
|
154
|
+
})
|
|
155
|
+
const [error, setError] = useState("")
|
|
156
|
+
const [loading, setLoading] = useState(false)
|
|
157
|
+
|
|
158
|
+
const handleSubmit = async (e) => {
|
|
159
|
+
e.preventDefault()
|
|
160
|
+
|
|
161
|
+
if (formData.password !== formData.confirm_password) {
|
|
162
|
+
setError("Passwords do not match")
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
setLoading(true)
|
|
167
|
+
try {
|
|
168
|
+
const userClient = new User(taruviClient)
|
|
169
|
+
await userClient.createUser(formData)
|
|
170
|
+
navigate("/login")
|
|
171
|
+
} catch (err) {
|
|
172
|
+
setError(err.message || "Failed to create user")
|
|
173
|
+
} finally {
|
|
174
|
+
setLoading(false)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<form onSubmit={handleSubmit}>
|
|
180
|
+
<input
|
|
181
|
+
name="username"
|
|
182
|
+
value={formData.username}
|
|
183
|
+
onChange={(e) => setFormData({...formData, username: e.target.value})}
|
|
184
|
+
required
|
|
185
|
+
/>
|
|
186
|
+
{/* Add other fields */}
|
|
187
|
+
<button type="submit" disabled={loading}>
|
|
188
|
+
{loading ? "Creating..." : "Register"}
|
|
189
|
+
</button>
|
|
190
|
+
{error && <div>{error}</div>}
|
|
191
|
+
</form>
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Database Service (CRUD Operations)
|
|
199
|
+
|
|
200
|
+
### Fetch All Records
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { Database } from '@taruvi-io/sdk'
|
|
204
|
+
|
|
205
|
+
const db = new Database(taruviClient)
|
|
206
|
+
const response = await db.from("accounts").execute()
|
|
207
|
+
|
|
208
|
+
if (response.data) {
|
|
209
|
+
console.log(response.data) // Array of records
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Fetch Single Record
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
const db = new Database(taruviClient)
|
|
217
|
+
const record = await db.from("accounts").get("record-id").execute()
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Update Record
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
const db = new Database(taruviClient)
|
|
224
|
+
await db.from("accounts").get("record-id").update({
|
|
225
|
+
name: "Updated Name",
|
|
226
|
+
status: "active"
|
|
227
|
+
}).execute()
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Delete Record
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
const db = new Database(taruviClient)
|
|
234
|
+
await db.from("accounts").delete("record-id").execute()
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Filter Records
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
const db = new Database(taruviClient)
|
|
241
|
+
const filtered = await db
|
|
242
|
+
.from("accounts")
|
|
243
|
+
.filter({
|
|
244
|
+
status: "active",
|
|
245
|
+
country: "USA"
|
|
246
|
+
})
|
|
247
|
+
.execute()
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Complete CRUD Example (CRM Table)
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import { useEffect, useState } from 'react'
|
|
254
|
+
import { Database } from '@taruvi-io/sdk'
|
|
255
|
+
|
|
256
|
+
export default function CrmTable({ taruviClient }) {
|
|
257
|
+
const [contacts, setContacts] = useState([])
|
|
258
|
+
|
|
259
|
+
const fetchContacts = async () => {
|
|
260
|
+
const db = new Database(taruviClient)
|
|
261
|
+
const response = await db.from("accounts").execute()
|
|
262
|
+
if (response.data) {
|
|
263
|
+
setContacts(response.data)
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
useEffect(() => {
|
|
268
|
+
fetchContacts()
|
|
269
|
+
}, [])
|
|
270
|
+
|
|
271
|
+
const handleDelete = async (id) => {
|
|
272
|
+
const db = new Database(taruviClient)
|
|
273
|
+
await db.from("accounts").delete(id).execute()
|
|
274
|
+
fetchContacts() // Refresh
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const handleUpdate = async (id, data) => {
|
|
278
|
+
const db = new Database(taruviClient)
|
|
279
|
+
await db.from("accounts").get(id).update(data).execute()
|
|
280
|
+
fetchContacts() // Refresh
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return (
|
|
284
|
+
<table>
|
|
285
|
+
{contacts.map(contact => (
|
|
286
|
+
<tr key={contact.id}>
|
|
287
|
+
<td>{contact.name}</td>
|
|
288
|
+
<td>
|
|
289
|
+
<button onClick={() => handleUpdate(contact.id, { status: 'updated' })}>
|
|
290
|
+
Edit
|
|
291
|
+
</button>
|
|
292
|
+
<button onClick={() => handleDelete(contact.id)}>
|
|
293
|
+
Delete
|
|
294
|
+
</button>
|
|
295
|
+
</td>
|
|
296
|
+
</tr>
|
|
297
|
+
))}
|
|
298
|
+
</table>
|
|
299
|
+
)
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Storage Service (File Management)
|
|
306
|
+
|
|
307
|
+
### List Files in Bucket
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
import { Storage } from '@taruvi-io/sdk'
|
|
311
|
+
|
|
312
|
+
const storage = new Storage(taruviClient, {})
|
|
313
|
+
const files = await storage.from("documents").execute()
|
|
314
|
+
|
|
315
|
+
console.log(files.data) // Array of file objects
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Upload Files
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
const storage = new Storage(taruviClient, {})
|
|
322
|
+
|
|
323
|
+
const filesData = {
|
|
324
|
+
files: [file1, file2], // File objects from input
|
|
325
|
+
metadatas: [{ name: "file1" }, { name: "file2" }],
|
|
326
|
+
paths: ["file1.pdf", "file2.pdf"]
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
await storage.from("documents").upload(filesData).execute()
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Delete File
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
const storage = new Storage(taruviClient, {})
|
|
336
|
+
await storage.from("documents").delete("path/to/file.pdf").execute()
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Update File Metadata
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
const storage = new Storage(taruviClient, {})
|
|
343
|
+
await storage
|
|
344
|
+
.from("documents")
|
|
345
|
+
.update("path/to/file.pdf", {
|
|
346
|
+
filename: "newname.pdf",
|
|
347
|
+
visibility: "public",
|
|
348
|
+
metadata: { category: "reports" }
|
|
349
|
+
})
|
|
350
|
+
.execute()
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Filter Files
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
const storage = new Storage(taruviClient, {})
|
|
357
|
+
const filtered = await storage
|
|
358
|
+
.from("documents")
|
|
359
|
+
.filter({
|
|
360
|
+
search: "invoice",
|
|
361
|
+
visibility: "public",
|
|
362
|
+
mimetype_category: "document",
|
|
363
|
+
min_size: 1024,
|
|
364
|
+
ordering: "-created_at"
|
|
365
|
+
})
|
|
366
|
+
.execute()
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Complete File Upload Example
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
import { useState, useRef } from 'react'
|
|
373
|
+
import { Storage } from '@taruvi-io/sdk'
|
|
374
|
+
|
|
375
|
+
export default function FileUploader({ taruviClient }) {
|
|
376
|
+
const [files, setFiles] = useState([])
|
|
377
|
+
const [uploading, setUploading] = useState(false)
|
|
378
|
+
const fileInputRef = useRef(null)
|
|
379
|
+
|
|
380
|
+
const handleFileSelect = (e) => {
|
|
381
|
+
const selectedFiles = Array.from(e.target.files)
|
|
382
|
+
setFiles(selectedFiles)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const uploadFiles = async () => {
|
|
386
|
+
if (files.length === 0) return
|
|
387
|
+
|
|
388
|
+
setUploading(true)
|
|
389
|
+
try {
|
|
390
|
+
const storage = new Storage(taruviClient, {})
|
|
391
|
+
|
|
392
|
+
const uploadData = {
|
|
393
|
+
files: files,
|
|
394
|
+
metadatas: files.map(f => ({ name: f.name })),
|
|
395
|
+
paths: files.map(f => f.name)
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
await storage.from("documents").upload(uploadData).execute()
|
|
399
|
+
|
|
400
|
+
alert("Upload successful!")
|
|
401
|
+
setFiles([])
|
|
402
|
+
} catch (error) {
|
|
403
|
+
alert("Upload failed: " + error.message)
|
|
404
|
+
} finally {
|
|
405
|
+
setUploading(false)
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
return (
|
|
410
|
+
<div>
|
|
411
|
+
<input
|
|
412
|
+
ref={fileInputRef}
|
|
413
|
+
type="file"
|
|
414
|
+
multiple
|
|
415
|
+
onChange={handleFileSelect}
|
|
416
|
+
/>
|
|
417
|
+
<button onClick={uploadFiles} disabled={uploading || files.length === 0}>
|
|
418
|
+
{uploading ? "Uploading..." : `Upload ${files.length} file(s)`}
|
|
419
|
+
</button>
|
|
420
|
+
</div>
|
|
421
|
+
)
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
## Functions Service (Serverless)
|
|
428
|
+
|
|
429
|
+
### Execute Function (Sync)
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
import { Functions } from '@taruvi-io/sdk'
|
|
433
|
+
|
|
434
|
+
const functions = new Functions(taruviClient)
|
|
435
|
+
|
|
436
|
+
const result = await functions.execute("my-function", {
|
|
437
|
+
async: false,
|
|
438
|
+
params: {
|
|
439
|
+
key1: "value1",
|
|
440
|
+
key2: 123
|
|
441
|
+
}
|
|
442
|
+
})
|
|
443
|
+
|
|
444
|
+
console.log(result.data) // Function response
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### Execute Function (Async)
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
const functions = new Functions(taruviClient)
|
|
451
|
+
|
|
452
|
+
const result = await functions.execute("long-running-task", {
|
|
453
|
+
async: true,
|
|
454
|
+
params: { data: "value" }
|
|
455
|
+
})
|
|
456
|
+
|
|
457
|
+
console.log(result.invocation.invocation_id) // Track async execution
|
|
458
|
+
console.log(result.invocation.celery_task_id)
|
|
459
|
+
console.log(result.invocation.status)
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### Complete Function Executor Example
|
|
463
|
+
|
|
464
|
+
```typescript
|
|
465
|
+
import { useState } from 'react'
|
|
466
|
+
import { Functions } from '@taruvi-io/sdk'
|
|
467
|
+
|
|
468
|
+
export default function FunctionExecutor({ taruviClient }) {
|
|
469
|
+
const [functionSlug, setFunctionSlug] = useState("")
|
|
470
|
+
const [params, setParams] = useState({})
|
|
471
|
+
const [isAsync, setIsAsync] = useState(false)
|
|
472
|
+
const [result, setResult] = useState(null)
|
|
473
|
+
const [loading, setLoading] = useState(false)
|
|
474
|
+
|
|
475
|
+
const executeFunction = async () => {
|
|
476
|
+
setLoading(true)
|
|
477
|
+
try {
|
|
478
|
+
const functions = new Functions(taruviClient)
|
|
479
|
+
const response = await functions.execute(functionSlug, {
|
|
480
|
+
async: isAsync,
|
|
481
|
+
params: params
|
|
482
|
+
})
|
|
483
|
+
setResult(response)
|
|
484
|
+
} catch (error) {
|
|
485
|
+
console.error(error)
|
|
486
|
+
} finally {
|
|
487
|
+
setLoading(false)
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
return (
|
|
492
|
+
<div>
|
|
493
|
+
<input
|
|
494
|
+
placeholder="Function slug"
|
|
495
|
+
value={functionSlug}
|
|
496
|
+
onChange={(e) => setFunctionSlug(e.target.value)}
|
|
497
|
+
/>
|
|
498
|
+
<label>
|
|
499
|
+
<input
|
|
500
|
+
type="checkbox"
|
|
501
|
+
checked={isAsync}
|
|
502
|
+
onChange={(e) => setIsAsync(e.target.checked)}
|
|
503
|
+
/>
|
|
504
|
+
Async
|
|
505
|
+
</label>
|
|
506
|
+
<button onClick={executeFunction} disabled={loading}>
|
|
507
|
+
Execute
|
|
508
|
+
</button>
|
|
509
|
+
{result && <pre>{JSON.stringify(result, null, 2)}</pre>}
|
|
510
|
+
</div>
|
|
511
|
+
)
|
|
512
|
+
}
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
## Settings Service
|
|
518
|
+
|
|
519
|
+
### Get Site Settings
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
import { Settings } from '@taruvi-io/sdk'
|
|
523
|
+
|
|
524
|
+
const settings = new Settings(taruviClient)
|
|
525
|
+
const config = await settings.get()
|
|
526
|
+
|
|
527
|
+
console.log(config) // Site configuration object
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### Update Setting
|
|
531
|
+
|
|
532
|
+
```typescript
|
|
533
|
+
const settings = new Settings(taruviClient)
|
|
534
|
+
await settings.update("setting_key", { value: "new_value" }).execute()
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
## Secrets Service
|
|
540
|
+
|
|
541
|
+
### List Secrets
|
|
542
|
+
|
|
543
|
+
```typescript
|
|
544
|
+
import { Secrets } from '@taruvi-io/sdk'
|
|
545
|
+
|
|
546
|
+
const secrets = new Secrets(taruviClient)
|
|
547
|
+
const result = await secrets.list().execute()
|
|
548
|
+
|
|
549
|
+
console.log(result.items) // Array of secrets
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### Update Secret
|
|
553
|
+
|
|
554
|
+
```typescript
|
|
555
|
+
const secrets = new Secrets(taruviClient)
|
|
556
|
+
|
|
557
|
+
await secrets.update("MY_SECRET", {
|
|
558
|
+
value: {
|
|
559
|
+
hostname: "db.example.com",
|
|
560
|
+
port_number: 3306,
|
|
561
|
+
username: "admin",
|
|
562
|
+
password: "secret123"
|
|
563
|
+
},
|
|
564
|
+
tags: ["mysql", "production"],
|
|
565
|
+
secret_type: "Mysql"
|
|
566
|
+
}).execute()
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
---
|
|
570
|
+
|
|
571
|
+
## Common Patterns
|
|
572
|
+
|
|
573
|
+
### Loading States
|
|
574
|
+
|
|
575
|
+
```typescript
|
|
576
|
+
const [data, setData] = useState(null)
|
|
577
|
+
const [loading, setLoading] = useState(true)
|
|
578
|
+
const [error, setError] = useState(null)
|
|
579
|
+
|
|
580
|
+
useEffect(() => {
|
|
581
|
+
const fetchData = async () => {
|
|
582
|
+
setLoading(true)
|
|
583
|
+
try {
|
|
584
|
+
const db = new Database(taruviClient)
|
|
585
|
+
const response = await db.from("table").execute()
|
|
586
|
+
setData(response.data)
|
|
587
|
+
} catch (err) {
|
|
588
|
+
setError(err.message)
|
|
589
|
+
} finally {
|
|
590
|
+
setLoading(false)
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
fetchData()
|
|
594
|
+
}, [])
|
|
595
|
+
|
|
596
|
+
if (loading) return <div>Loading...</div>
|
|
597
|
+
if (error) return <div>Error: {error}</div>
|
|
598
|
+
return <div>{/* Render data */}</div>
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
### Error Handling
|
|
602
|
+
|
|
603
|
+
```typescript
|
|
604
|
+
try {
|
|
605
|
+
const user = new User(taruviClient)
|
|
606
|
+
await user.createUser(data)
|
|
607
|
+
} catch (error) {
|
|
608
|
+
if (error.response?.status === 400) {
|
|
609
|
+
console.error("Validation error:", error.response.data)
|
|
610
|
+
} else if (error.response?.status === 401) {
|
|
611
|
+
console.error("Unauthorized")
|
|
612
|
+
} else {
|
|
613
|
+
console.error("Unknown error:", error.message)
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
### Refresh Data After Mutation
|
|
619
|
+
|
|
620
|
+
```typescript
|
|
621
|
+
const [items, setItems] = useState([])
|
|
622
|
+
|
|
623
|
+
const fetchItems = async () => {
|
|
624
|
+
const db = new Database(taruviClient)
|
|
625
|
+
const response = await db.from("items").execute()
|
|
626
|
+
setItems(response.data || [])
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
const deleteItem = async (id) => {
|
|
630
|
+
const db = new Database(taruviClient)
|
|
631
|
+
await db.from("items").delete(id).execute()
|
|
632
|
+
await fetchItems() // Refresh list
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
const updateItem = async (id, data) => {
|
|
636
|
+
const db = new Database(taruviClient)
|
|
637
|
+
await db.from("items").get(id).update(data).execute()
|
|
638
|
+
await fetchItems() // Refresh list
|
|
639
|
+
}
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
---
|
|
643
|
+
|
|
644
|
+
## TypeScript Types
|
|
645
|
+
|
|
646
|
+
### Import Types
|
|
647
|
+
|
|
648
|
+
```typescript
|
|
649
|
+
import type {
|
|
650
|
+
TaruviConfig,
|
|
651
|
+
UserCreateRequest,
|
|
652
|
+
UserResponse,
|
|
653
|
+
UserDataResponse,
|
|
654
|
+
FunctionRequest,
|
|
655
|
+
FunctionResponse,
|
|
656
|
+
StorageFilters,
|
|
657
|
+
DatabaseFilters
|
|
658
|
+
} from '@taruvi-io/sdk'
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
### Type Usage
|
|
662
|
+
|
|
663
|
+
```typescript
|
|
664
|
+
const config: TaruviConfig = {
|
|
665
|
+
apiKey: "key",
|
|
666
|
+
appSlug: "app",
|
|
667
|
+
baseUrl: "https://api.taruvi.cloud"
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
const userData: UserCreateRequest = {
|
|
671
|
+
username: "john",
|
|
672
|
+
email: "john@example.com",
|
|
673
|
+
password: "pass123",
|
|
674
|
+
confirm_password: "pass123",
|
|
675
|
+
first_name: "John",
|
|
676
|
+
last_name: "Doe"
|
|
677
|
+
}
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
---
|
|
681
|
+
|
|
682
|
+
## Quick Reference
|
|
683
|
+
|
|
684
|
+
| Service | Import | Purpose |
|
|
685
|
+
|---------|--------|---------|
|
|
686
|
+
| `Client` | `import { Client }` | Main SDK client |
|
|
687
|
+
| `Auth` | `import { Auth }` | Authentication |
|
|
688
|
+
| `User` | `import { User }` | User management |
|
|
689
|
+
| `Database` | `import { Database }` | App data CRUD |
|
|
690
|
+
| `Storage` | `import { Storage }` | File management |
|
|
691
|
+
| `Functions` | `import { Functions }` | Serverless functions |
|
|
692
|
+
| `Settings` | `import { Settings }` | Site configuration |
|
|
693
|
+
| `Secrets` | `import { Secrets }` | Sensitive data |
|
|
694
|
+
|
|
695
|
+
---
|
|
696
|
+
|
|
697
|
+
## Chaining Pattern
|
|
698
|
+
|
|
699
|
+
All query-building services use method chaining:
|
|
700
|
+
|
|
701
|
+
```typescript
|
|
702
|
+
// Database
|
|
703
|
+
await db.from("table").get("id").update(data).execute()
|
|
704
|
+
await db.from("table").filter({ status: "active" }).execute()
|
|
705
|
+
|
|
706
|
+
// Storage
|
|
707
|
+
await storage.from("bucket").delete("path").execute()
|
|
708
|
+
await storage.from("bucket").filter({ search: "query" }).execute()
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
**Always call `.execute()` at the end to run the query!**
|
|
712
|
+
|
|
713
|
+
---
|
|
714
|
+
|
|
715
|
+
## Environment Variables
|
|
716
|
+
|
|
717
|
+
```env
|
|
718
|
+
VITE_TARUVI_API_KEY=your-api-key
|
|
719
|
+
VITE_TARUVI_APP_SLUG=your-app
|
|
720
|
+
VITE_TARUVI_BASE_URL=https://taruvi-site.taruvi.cloud
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
```typescript
|
|
724
|
+
const client = new Client({
|
|
725
|
+
apiKey: import.meta.env.VITE_TARUVI_API_KEY,
|
|
726
|
+
appSlug: import.meta.env.VITE_TARUVI_APP_SLUG,
|
|
727
|
+
baseUrl: import.meta.env.VITE_TARUVI_BASE_URL
|
|
728
|
+
})
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
---
|
|
732
|
+
|
|
733
|
+
**Generated from production code examples • Last updated: 2025-12-15**
|