@tapstack/db 1.0.7 → 3.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.
- package/README.md +655 -0
- package/dist/adapters/index.d.ts +6 -0
- package/dist/adapters/index.js +22 -0
- package/dist/adapters/nodejs.adapter.d.ts +63 -0
- package/dist/adapters/nodejs.adapter.js +204 -0
- package/dist/adapters/types.d.ts +77 -0
- package/dist/adapters/types.js +19 -0
- package/dist/index.d.ts +101 -21
- package/dist/index.js +114 -41
- package/dist/modules/automations.d.ts +109 -0
- package/dist/modules/automations.js +59 -0
- package/dist/modules/conversations.d.ts +82 -0
- package/dist/modules/conversations.js +54 -0
- package/dist/modules/fields.d.ts +30 -9
- package/dist/modules/fields.js +31 -13
- package/dist/modules/files.d.ts +68 -0
- package/dist/modules/files.js +115 -0
- package/dist/modules/index.d.ts +12 -0
- package/dist/modules/index.js +28 -0
- package/dist/modules/objects.d.ts +30 -9
- package/dist/modules/objects.js +35 -13
- package/dist/modules/organizations.d.ts +69 -0
- package/dist/modules/organizations.js +83 -0
- package/dist/modules/records.d.ts +47 -5
- package/dist/modules/records.js +70 -5
- package/dist/modules/workspaces.d.ts +44 -0
- package/dist/modules/workspaces.js +57 -0
- package/dist/types.d.ts +159 -10
- package/dist/types.js +19 -0
- package/package.json +16 -7
- package/src/__tests__/client.test.ts +305 -49
- package/src/adapters/index.ts +13 -0
- package/src/adapters/nodejs.adapter.ts +298 -0
- package/src/adapters/types.ts +108 -0
- package/src/index.ts +132 -44
- package/src/modules/automations.ts +157 -0
- package/src/modules/conversations.ts +134 -0
- package/src/modules/fields.ts +64 -14
- package/src/modules/files.ts +144 -0
- package/src/modules/index.ts +19 -0
- package/src/modules/objects.ts +46 -14
- package/src/modules/organizations.ts +137 -0
- package/src/modules/records.ts +119 -6
- package/src/modules/workspaces.ts +95 -0
- package/src/types.ts +229 -9
- package/dist/request.d.ts +0 -2
- package/dist/request.js +0 -20
- package/src/request.ts +0 -14
package/README.md
ADDED
|
@@ -0,0 +1,655 @@
|
|
|
1
|
+
# @tapstack/db
|
|
2
|
+
|
|
3
|
+
Official SDK for the [Tapstack API](https://api.tapstack.com). Build applications with a Notion-like database backend featuring objects (models), fields, records, file storage, automations, and more.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @tapstack/db
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { createClient } from '@tapstack/db';
|
|
15
|
+
|
|
16
|
+
// Create a client with API key authentication
|
|
17
|
+
const client = createClient({
|
|
18
|
+
apiKey: 'your-api-key',
|
|
19
|
+
workspaceId: 'your-workspace-id',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// List all objects in the workspace
|
|
23
|
+
const { objects } = await client.objects.list();
|
|
24
|
+
|
|
25
|
+
// Create a record
|
|
26
|
+
const record = await client.records.create('contacts', {
|
|
27
|
+
data: {
|
|
28
|
+
name: 'John Doe',
|
|
29
|
+
email: 'john@example.com',
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Configuration
|
|
35
|
+
|
|
36
|
+
### Basic Configuration
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { createClient } from '@tapstack/db';
|
|
40
|
+
|
|
41
|
+
const client = createClient({
|
|
42
|
+
// API URL (optional, defaults to https://api.tapstack.com)
|
|
43
|
+
baseUrl: 'https://api.tapstack.com',
|
|
44
|
+
|
|
45
|
+
// Authentication (choose one)
|
|
46
|
+
apiKey: 'your-api-key', // For server-side/programmatic access
|
|
47
|
+
userToken: 'jwt-token', // For authenticated user sessions
|
|
48
|
+
|
|
49
|
+
// Workspace context
|
|
50
|
+
workspaceId: 'workspace-uuid',
|
|
51
|
+
|
|
52
|
+
// Error handling
|
|
53
|
+
onAuthError: () => {
|
|
54
|
+
// Handle authentication errors (e.g., redirect to login)
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Frontend Configuration (Dynamic Token)
|
|
60
|
+
|
|
61
|
+
For frontend applications where the access token may change:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
const client = createClient({
|
|
65
|
+
getUserToken: async () => {
|
|
66
|
+
// Return the current access token from your auth state
|
|
67
|
+
return localStorage.getItem('access_token');
|
|
68
|
+
},
|
|
69
|
+
workspaceId: 'workspace-uuid',
|
|
70
|
+
onAuthError: () => {
|
|
71
|
+
// Redirect to login
|
|
72
|
+
window.location.href = '/login';
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Switching Workspaces
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
// Set workspace context for all subsequent requests
|
|
81
|
+
client.setWorkspaceId('new-workspace-id');
|
|
82
|
+
|
|
83
|
+
// Get current workspace ID
|
|
84
|
+
const workspaceId = client.getWorkspaceId();
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Objects (Models)
|
|
88
|
+
|
|
89
|
+
Objects define your data schema, similar to tables in a database or models in Notion.
|
|
90
|
+
|
|
91
|
+
### List Objects
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const { objects } = await client.objects.list();
|
|
95
|
+
|
|
96
|
+
for (const obj of objects) {
|
|
97
|
+
console.log(`${obj.icon} ${obj.pluralName} (${obj.slug})`);
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Get Object by Slug
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
const contacts = await client.objects.get('contacts');
|
|
105
|
+
console.log(contacts.singleName); // "Contact"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Create Object
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
const newObject = await client.objects.create({
|
|
112
|
+
singleName: 'Contact',
|
|
113
|
+
pluralName: 'Contacts',
|
|
114
|
+
slug: 'contacts', // Optional, auto-generated if not provided
|
|
115
|
+
icon: '👤', // Optional
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Update Object
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
const updated = await client.objects.update('contacts', {
|
|
123
|
+
singleName: 'Customer',
|
|
124
|
+
pluralName: 'Customers',
|
|
125
|
+
icon: '🧑💼',
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Delete Object
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// Soft delete (default)
|
|
133
|
+
await client.objects.delete('contacts');
|
|
134
|
+
|
|
135
|
+
// Hard delete
|
|
136
|
+
await client.objects.delete('contacts', false);
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Fields
|
|
140
|
+
|
|
141
|
+
Fields define the schema of an object, similar to columns in a database.
|
|
142
|
+
|
|
143
|
+
### Supported Field Types
|
|
144
|
+
|
|
145
|
+
- `text` - Plain text
|
|
146
|
+
- `number` - Numeric values
|
|
147
|
+
- `boolean` - True/false
|
|
148
|
+
- `date` - Date only
|
|
149
|
+
- `datetime` - Date and time
|
|
150
|
+
- `email` - Email address
|
|
151
|
+
- `phone` - Phone number
|
|
152
|
+
- `url` - URL/link
|
|
153
|
+
- `select` / `single_select` - Single selection dropdown
|
|
154
|
+
- `multi_select` - Multiple selection
|
|
155
|
+
- `checkbox` - Checkbox
|
|
156
|
+
- `relation` - Relationship to another object
|
|
157
|
+
- `currency` - Currency values
|
|
158
|
+
- `rating` - Star rating
|
|
159
|
+
- `textarea` - Long text
|
|
160
|
+
- `json` - JSON data
|
|
161
|
+
- `files` - File attachments
|
|
162
|
+
- `person` - User reference
|
|
163
|
+
- `ai` - AI-generated field
|
|
164
|
+
|
|
165
|
+
### List Fields
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
const { fields } = await client.fields.list('contacts');
|
|
169
|
+
|
|
170
|
+
for (const field of fields) {
|
|
171
|
+
console.log(`${field.label}: ${field.type}`);
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Create Field
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
const emailField = await client.fields.create('contacts', {
|
|
179
|
+
label: 'Email',
|
|
180
|
+
value: 'email', // Field key (used in record data)
|
|
181
|
+
type: 'email',
|
|
182
|
+
data: {
|
|
183
|
+
required: true,
|
|
184
|
+
placeholder: 'Enter email address',
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Create a select field with options
|
|
189
|
+
const statusField = await client.fields.create('contacts', {
|
|
190
|
+
label: 'Status',
|
|
191
|
+
value: 'status',
|
|
192
|
+
type: 'single_select',
|
|
193
|
+
data: {
|
|
194
|
+
options: [
|
|
195
|
+
{ label: 'Active', value: 'active', color: '#22c55e' },
|
|
196
|
+
{ label: 'Inactive', value: 'inactive', color: '#ef4444' },
|
|
197
|
+
],
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Create a relation field
|
|
202
|
+
const companyField = await client.fields.create('contacts', {
|
|
203
|
+
label: 'Company',
|
|
204
|
+
value: 'company',
|
|
205
|
+
type: 'relation',
|
|
206
|
+
data: {
|
|
207
|
+
relatedObjectId: 'companies-object-uuid',
|
|
208
|
+
relationType: 'many-to-one',
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Update Field
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
const updated = await client.fields.update('contacts', 'field-id', {
|
|
217
|
+
label: 'Email Address',
|
|
218
|
+
data: {
|
|
219
|
+
required: false,
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Delete Field
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
await client.fields.delete('contacts', 'field-id');
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Records
|
|
231
|
+
|
|
232
|
+
Records are the data entries within an object.
|
|
233
|
+
|
|
234
|
+
### List Records
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
const response = await client.records.list('contacts', {
|
|
238
|
+
page: 1,
|
|
239
|
+
pageSize: 50,
|
|
240
|
+
sortBy: 'createdAt',
|
|
241
|
+
sortOrder: 'desc',
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
console.log(`Total: ${response.total}`);
|
|
245
|
+
for (const record of response.items) {
|
|
246
|
+
console.log(record.data.name);
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Get Record
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
const record = await client.records.get('contacts', 'record-id');
|
|
254
|
+
console.log(record.data);
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Create Record
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
const record = await client.records.create('contacts', {
|
|
261
|
+
data: {
|
|
262
|
+
name: 'Jane Smith',
|
|
263
|
+
email: 'jane@example.com',
|
|
264
|
+
status: 'active',
|
|
265
|
+
company: 'company-record-id', // Relation field
|
|
266
|
+
},
|
|
267
|
+
status: 'published', // Optional: 'draft' | 'published'
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Update Record
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
const updated = await client.records.update('contacts', 'record-id', {
|
|
275
|
+
data: {
|
|
276
|
+
name: 'Jane Doe',
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Delete Record
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
// Soft delete (default)
|
|
285
|
+
await client.records.delete('contacts', 'record-id');
|
|
286
|
+
|
|
287
|
+
// Hard delete
|
|
288
|
+
await client.records.delete('contacts', 'record-id', false);
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Bulk Operations
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
// Bulk create
|
|
295
|
+
const { records, count } = await client.records.bulkCreate('contacts', [
|
|
296
|
+
{ data: { name: 'Contact 1', email: 'contact1@example.com' } },
|
|
297
|
+
{ data: { name: 'Contact 2', email: 'contact2@example.com' } },
|
|
298
|
+
{ data: { name: 'Contact 3', email: 'contact3@example.com' } },
|
|
299
|
+
]);
|
|
300
|
+
|
|
301
|
+
// Bulk delete
|
|
302
|
+
const { deleted } = await client.records.bulkDelete('contacts', [
|
|
303
|
+
'record-id-1',
|
|
304
|
+
'record-id-2',
|
|
305
|
+
]);
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Advanced Queries
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
const results = await client.records.query('contacts', {
|
|
312
|
+
filter: {
|
|
313
|
+
and: [
|
|
314
|
+
{ field: 'status', op: 'eq', value: 'active' },
|
|
315
|
+
{ field: 'createdAt', op: 'gte', value: Date.now() - 86400000 },
|
|
316
|
+
],
|
|
317
|
+
},
|
|
318
|
+
sort: [
|
|
319
|
+
{ field: 'name', direction: 'asc' },
|
|
320
|
+
],
|
|
321
|
+
limit: 100,
|
|
322
|
+
});
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## Organizations & Workspaces
|
|
326
|
+
|
|
327
|
+
Tapstack uses a multi-tenant architecture with Organizations containing Workspaces.
|
|
328
|
+
|
|
329
|
+
### Organizations
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
// List organizations the user belongs to
|
|
333
|
+
const { organizations } = await client.organizations.list();
|
|
334
|
+
|
|
335
|
+
// Create an organization
|
|
336
|
+
const org = await client.organizations.create({
|
|
337
|
+
name: 'Acme Corp',
|
|
338
|
+
slug: 'acme-corp',
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
// Get organization details
|
|
342
|
+
const org = await client.organizations.get('org-id');
|
|
343
|
+
|
|
344
|
+
// Update organization
|
|
345
|
+
await client.organizations.update('org-id', {
|
|
346
|
+
name: 'Acme Corporation',
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
// List organization members
|
|
350
|
+
const { members } = await client.organizations.listMembers('org-id');
|
|
351
|
+
|
|
352
|
+
// Add a member
|
|
353
|
+
await client.organizations.addMember('org-id', {
|
|
354
|
+
email: 'newuser@example.com',
|
|
355
|
+
role: 'member',
|
|
356
|
+
});
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### Workspaces
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
// List all workspaces
|
|
363
|
+
const { workspaces } = await client.workspaces.list();
|
|
364
|
+
|
|
365
|
+
// Create a workspace in an organization
|
|
366
|
+
const workspace = await client.workspaces.create('org-id', {
|
|
367
|
+
name: 'Production',
|
|
368
|
+
slug: 'production',
|
|
369
|
+
description: 'Production environment',
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
// Get workspace by ID
|
|
373
|
+
const ws = await client.workspaces.get('workspace-id');
|
|
374
|
+
|
|
375
|
+
// Resolve workspace by slugs (useful for routing)
|
|
376
|
+
const ws = await client.workspaces.resolveBySlug('acme-corp', 'production');
|
|
377
|
+
|
|
378
|
+
// Get workspace statistics
|
|
379
|
+
const stats = await client.workspaces.getStats('workspace-id');
|
|
380
|
+
console.log(`Objects: ${stats.objectCount}, Records: ${stats.recordCount}`);
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## File Storage
|
|
384
|
+
|
|
385
|
+
Upload and manage files within your workspace.
|
|
386
|
+
|
|
387
|
+
### Upload Files
|
|
388
|
+
|
|
389
|
+
```typescript
|
|
390
|
+
// Upload a file
|
|
391
|
+
const file = await client.files.upload(fileBlob, {
|
|
392
|
+
folderId: 'folder-id', // Optional
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
console.log(`Uploaded: ${file.name} (${file.size} bytes)`);
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### List Files
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
// List all files
|
|
402
|
+
const { files } = await client.files.list();
|
|
403
|
+
|
|
404
|
+
// List files in a specific folder
|
|
405
|
+
const { files } = await client.files.list('folder-id');
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Download Files
|
|
409
|
+
|
|
410
|
+
```typescript
|
|
411
|
+
// Get a signed download URL
|
|
412
|
+
const { url } = await client.files.getDownloadUrl('file-id', 3600); // 1 hour expiry
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### File Operations
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
// Rename a file
|
|
419
|
+
await client.files.rename('file-id', 'new-name.pdf');
|
|
420
|
+
|
|
421
|
+
// Move to another folder
|
|
422
|
+
await client.files.move('file-id', 'target-folder-id');
|
|
423
|
+
|
|
424
|
+
// Delete a file
|
|
425
|
+
await client.files.delete('file-id');
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Folders
|
|
429
|
+
|
|
430
|
+
```typescript
|
|
431
|
+
// List folders
|
|
432
|
+
const { folders } = await client.files.listFolders();
|
|
433
|
+
|
|
434
|
+
// List subfolders
|
|
435
|
+
const { folders } = await client.files.listFolders('parent-folder-id');
|
|
436
|
+
|
|
437
|
+
// Create a folder
|
|
438
|
+
const folder = await client.files.createFolder('Documents', 'parent-folder-id');
|
|
439
|
+
|
|
440
|
+
// Rename folder
|
|
441
|
+
await client.files.renameFolder('folder-id', 'New Name');
|
|
442
|
+
|
|
443
|
+
// Move folder
|
|
444
|
+
await client.files.moveFolder('folder-id', 'new-parent-id');
|
|
445
|
+
|
|
446
|
+
// Delete folder (and all contents)
|
|
447
|
+
await client.files.deleteFolder('folder-id');
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
## Automations
|
|
451
|
+
|
|
452
|
+
Create automated workflows triggered by record events.
|
|
453
|
+
|
|
454
|
+
### List Automations
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
const { automations } = await client.automations.list();
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### Create Automation
|
|
461
|
+
|
|
462
|
+
```typescript
|
|
463
|
+
const automation = await client.automations.create({
|
|
464
|
+
name: 'Send welcome email',
|
|
465
|
+
description: 'Sends a welcome email when a new contact is created',
|
|
466
|
+
triggerObjectId: 'contacts-object-id',
|
|
467
|
+
triggerType: 'record.created',
|
|
468
|
+
triggerConditions: [
|
|
469
|
+
{ field: 'status', operator: 'eq', value: 'active' },
|
|
470
|
+
],
|
|
471
|
+
actions: [
|
|
472
|
+
{
|
|
473
|
+
type: 'webhook',
|
|
474
|
+
config: {
|
|
475
|
+
url: 'https://api.example.com/send-email',
|
|
476
|
+
method: 'POST',
|
|
477
|
+
headers: { 'Authorization': 'Bearer token' },
|
|
478
|
+
body: '{"email": "{{record.email}}"}',
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
],
|
|
482
|
+
});
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
### Automation Triggers
|
|
486
|
+
|
|
487
|
+
- `record.created` - When a new record is created
|
|
488
|
+
- `record.updated` - When a record is updated
|
|
489
|
+
- `record.deleted` - When a record is deleted
|
|
490
|
+
|
|
491
|
+
### Automation Actions
|
|
492
|
+
|
|
493
|
+
- `create_record` - Create a record in another object
|
|
494
|
+
- `update_record` - Update related records
|
|
495
|
+
- `delete_record` - Delete related records
|
|
496
|
+
- `webhook` - Call an external webhook
|
|
497
|
+
|
|
498
|
+
### Manage Automations
|
|
499
|
+
|
|
500
|
+
```typescript
|
|
501
|
+
// Toggle enabled/disabled
|
|
502
|
+
await client.automations.toggle('automation-id');
|
|
503
|
+
|
|
504
|
+
// Update automation
|
|
505
|
+
await client.automations.update('automation-id', {
|
|
506
|
+
name: 'Updated name',
|
|
507
|
+
isEnabled: true,
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
// Test execute (for debugging)
|
|
511
|
+
const result = await client.automations.execute('automation-id', {
|
|
512
|
+
// Test data matching trigger schema
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
// Delete
|
|
516
|
+
await client.automations.delete('automation-id');
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
## AI Conversations
|
|
520
|
+
|
|
521
|
+
Manage AI chat conversations for building chatbots and assistants.
|
|
522
|
+
|
|
523
|
+
### Create Conversation
|
|
524
|
+
|
|
525
|
+
```typescript
|
|
526
|
+
const { conversation } = await client.conversations.create({
|
|
527
|
+
title: 'Support Chat',
|
|
528
|
+
});
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### List Conversations
|
|
532
|
+
|
|
533
|
+
```typescript
|
|
534
|
+
const { conversations, total } = await client.conversations.list({
|
|
535
|
+
limit: 20,
|
|
536
|
+
offset: 0,
|
|
537
|
+
});
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
### Add Messages
|
|
541
|
+
|
|
542
|
+
```typescript
|
|
543
|
+
// Add user message
|
|
544
|
+
await client.conversations.addMessage('conversation-id', {
|
|
545
|
+
role: 'user',
|
|
546
|
+
content: 'Hello, I need help!',
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
// Add assistant response
|
|
550
|
+
await client.conversations.addMessage('conversation-id', {
|
|
551
|
+
role: 'assistant',
|
|
552
|
+
content: 'Hi! How can I assist you today?',
|
|
553
|
+
});
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
### Get Conversation with Messages
|
|
557
|
+
|
|
558
|
+
```typescript
|
|
559
|
+
const conversation = await client.conversations.get('conversation-id');
|
|
560
|
+
|
|
561
|
+
for (const message of conversation.messages) {
|
|
562
|
+
console.log(`${message.role}: ${message.content}`);
|
|
563
|
+
}
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
## TypeScript Support
|
|
567
|
+
|
|
568
|
+
The SDK is fully typed. Import types as needed:
|
|
569
|
+
|
|
570
|
+
```typescript
|
|
571
|
+
import {
|
|
572
|
+
TapstackObject,
|
|
573
|
+
TapstackField,
|
|
574
|
+
TapstackRecord,
|
|
575
|
+
TapstackOrganization,
|
|
576
|
+
TapstackWorkspace,
|
|
577
|
+
TapstackFile,
|
|
578
|
+
FieldType,
|
|
579
|
+
RecordStatus,
|
|
580
|
+
CreateObjectPayload,
|
|
581
|
+
CreateFieldPayload,
|
|
582
|
+
CreateRecordPayload,
|
|
583
|
+
} from '@tapstack/db';
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
## Error Handling
|
|
587
|
+
|
|
588
|
+
The SDK throws `AdapterError` for API errors:
|
|
589
|
+
|
|
590
|
+
```typescript
|
|
591
|
+
import { AdapterError } from '@tapstack/db';
|
|
592
|
+
|
|
593
|
+
try {
|
|
594
|
+
await client.records.get('contacts', 'invalid-id');
|
|
595
|
+
} catch (error) {
|
|
596
|
+
if (error instanceof AdapterError) {
|
|
597
|
+
console.error(`Error: ${error.message}`);
|
|
598
|
+
console.error(`Code: ${error.code}`);
|
|
599
|
+
console.error(`Status: ${error.statusCode}`);
|
|
600
|
+
|
|
601
|
+
if (error.code === 'UNAUTHORIZED') {
|
|
602
|
+
// Handle auth error
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
## Custom Adapters
|
|
609
|
+
|
|
610
|
+
For advanced use cases, you can create a custom adapter:
|
|
611
|
+
|
|
612
|
+
```typescript
|
|
613
|
+
import { createCustomClient, IInstanceAdapter } from '@tapstack/db';
|
|
614
|
+
|
|
615
|
+
class MyCustomAdapter implements IInstanceAdapter {
|
|
616
|
+
async request<T>(method: string, path: string, options?: RequestOptions): Promise<T> {
|
|
617
|
+
// Your implementation
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
async upload<T>(path: string, file: File | Blob, metadata?: Record<string, string>): Promise<T> {
|
|
621
|
+
// Your implementation
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
setWorkspaceId(id: string | null): void {
|
|
625
|
+
// Your implementation
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
getWorkspaceId(): string | null {
|
|
629
|
+
// Your implementation
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
const client = createCustomClient(new MyCustomAdapter());
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
## Environment Variables
|
|
637
|
+
|
|
638
|
+
For Next.js or other frameworks, configure via environment variables:
|
|
639
|
+
|
|
640
|
+
```env
|
|
641
|
+
# .env.local
|
|
642
|
+
NEXT_PUBLIC_TAPSTACK_API_URL=https://api.tapstack.com
|
|
643
|
+
TAPSTACK_API_KEY=your-api-key
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
```typescript
|
|
647
|
+
const client = createClient({
|
|
648
|
+
baseUrl: process.env.NEXT_PUBLIC_TAPSTACK_API_URL,
|
|
649
|
+
apiKey: process.env.TAPSTACK_API_KEY,
|
|
650
|
+
});
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
## License
|
|
654
|
+
|
|
655
|
+
MIT
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Adapters Index
|
|
4
|
+
* Export all adapter types and implementations
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
18
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
__exportStar(require("./types"), exports);
|
|
22
|
+
__exportStar(require("./nodejs.adapter"), exports);
|