New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@tapstack/db

Package Overview
Dependencies
Maintainers
3
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tapstack/db

Tapstack Database Client - Official SDK for the Tapstack API

latest
npmnpm
Version
3.0.0
Version published
Weekly downloads
64
100%
Maintainers
3
Weekly downloads
 
Created
Source

@tapstack/db

Official SDK for the Tapstack API. Build applications with a Notion-like database backend featuring objects (models), fields, records, file storage, automations, and more.

Installation

npm install @tapstack/db

Quick Start

import { createClient } from '@tapstack/db';

// Create a client with API key authentication
const client = createClient({
  apiKey: 'your-api-key',
  workspaceId: 'your-workspace-id',
});

// List all objects in the workspace
const { objects } = await client.objects.list();

// Create a record
const record = await client.records.create('contacts', {
  data: {
    name: 'John Doe',
    email: 'john@example.com',
  },
});

Configuration

Basic Configuration

import { createClient } from '@tapstack/db';

const client = createClient({
  // API URL (optional, defaults to https://api.tapstack.com)
  baseUrl: 'https://api.tapstack.com',
  
  // Authentication (choose one)
  apiKey: 'your-api-key',           // For server-side/programmatic access
  userToken: 'jwt-token',           // For authenticated user sessions
  
  // Workspace context
  workspaceId: 'workspace-uuid',
  
  // Error handling
  onAuthError: () => {
    // Handle authentication errors (e.g., redirect to login)
  },
});

Frontend Configuration (Dynamic Token)

For frontend applications where the access token may change:

const client = createClient({
  getUserToken: async () => {
    // Return the current access token from your auth state
    return localStorage.getItem('access_token');
  },
  workspaceId: 'workspace-uuid',
  onAuthError: () => {
    // Redirect to login
    window.location.href = '/login';
  },
});

Switching Workspaces

// Set workspace context for all subsequent requests
client.setWorkspaceId('new-workspace-id');

// Get current workspace ID
const workspaceId = client.getWorkspaceId();

Objects (Models)

Objects define your data schema, similar to tables in a database or models in Notion.

List Objects

const { objects } = await client.objects.list();

for (const obj of objects) {
  console.log(`${obj.icon} ${obj.pluralName} (${obj.slug})`);
}

Get Object by Slug

const contacts = await client.objects.get('contacts');
console.log(contacts.singleName); // "Contact"

Create Object

const newObject = await client.objects.create({
  singleName: 'Contact',
  pluralName: 'Contacts',
  slug: 'contacts',       // Optional, auto-generated if not provided
  icon: '👤',             // Optional
});

Update Object

const updated = await client.objects.update('contacts', {
  singleName: 'Customer',
  pluralName: 'Customers',
  icon: '🧑‍💼',
});

Delete Object

// Soft delete (default)
await client.objects.delete('contacts');

// Hard delete
await client.objects.delete('contacts', false);

Fields

Fields define the schema of an object, similar to columns in a database.

Supported Field Types

  • text - Plain text
  • number - Numeric values
  • boolean - True/false
  • date - Date only
  • datetime - Date and time
  • email - Email address
  • phone - Phone number
  • url - URL/link
  • select / single_select - Single selection dropdown
  • multi_select - Multiple selection
  • checkbox - Checkbox
  • relation - Relationship to another object
  • currency - Currency values
  • rating - Star rating
  • textarea - Long text
  • json - JSON data
  • files - File attachments
  • person - User reference
  • ai - AI-generated field

List Fields

const { fields } = await client.fields.list('contacts');

for (const field of fields) {
  console.log(`${field.label}: ${field.type}`);
}

Create Field

const emailField = await client.fields.create('contacts', {
  label: 'Email',
  value: 'email',        // Field key (used in record data)
  type: 'email',
  data: {
    required: true,
    placeholder: 'Enter email address',
  },
});

// Create a select field with options
const statusField = await client.fields.create('contacts', {
  label: 'Status',
  value: 'status',
  type: 'single_select',
  data: {
    options: [
      { label: 'Active', value: 'active', color: '#22c55e' },
      { label: 'Inactive', value: 'inactive', color: '#ef4444' },
    ],
  },
});

// Create a relation field
const companyField = await client.fields.create('contacts', {
  label: 'Company',
  value: 'company',
  type: 'relation',
  data: {
    relatedObjectId: 'companies-object-uuid',
    relationType: 'many-to-one',
  },
});

Update Field

const updated = await client.fields.update('contacts', 'field-id', {
  label: 'Email Address',
  data: {
    required: false,
  },
});

Delete Field

await client.fields.delete('contacts', 'field-id');

Records

Records are the data entries within an object.

List Records

const response = await client.records.list('contacts', {
  page: 1,
  pageSize: 50,
  sortBy: 'createdAt',
  sortOrder: 'desc',
});

console.log(`Total: ${response.total}`);
for (const record of response.items) {
  console.log(record.data.name);
}

Get Record

const record = await client.records.get('contacts', 'record-id');
console.log(record.data);

Create Record

const record = await client.records.create('contacts', {
  data: {
    name: 'Jane Smith',
    email: 'jane@example.com',
    status: 'active',
    company: 'company-record-id',  // Relation field
  },
  status: 'published',  // Optional: 'draft' | 'published'
});

Update Record

const updated = await client.records.update('contacts', 'record-id', {
  data: {
    name: 'Jane Doe',
  },
});

Delete Record

// Soft delete (default)
await client.records.delete('contacts', 'record-id');

// Hard delete
await client.records.delete('contacts', 'record-id', false);

Bulk Operations

// Bulk create
const { records, count } = await client.records.bulkCreate('contacts', [
  { data: { name: 'Contact 1', email: 'contact1@example.com' } },
  { data: { name: 'Contact 2', email: 'contact2@example.com' } },
  { data: { name: 'Contact 3', email: 'contact3@example.com' } },
]);

// Bulk delete
const { deleted } = await client.records.bulkDelete('contacts', [
  'record-id-1',
  'record-id-2',
]);

Advanced Queries

const results = await client.records.query('contacts', {
  filter: {
    and: [
      { field: 'status', op: 'eq', value: 'active' },
      { field: 'createdAt', op: 'gte', value: Date.now() - 86400000 },
    ],
  },
  sort: [
    { field: 'name', direction: 'asc' },
  ],
  limit: 100,
});

Organizations & Workspaces

Tapstack uses a multi-tenant architecture with Organizations containing Workspaces.

Organizations

// List organizations the user belongs to
const { organizations } = await client.organizations.list();

// Create an organization
const org = await client.organizations.create({
  name: 'Acme Corp',
  slug: 'acme-corp',
});

// Get organization details
const org = await client.organizations.get('org-id');

// Update organization
await client.organizations.update('org-id', {
  name: 'Acme Corporation',
});

// List organization members
const { members } = await client.organizations.listMembers('org-id');

// Add a member
await client.organizations.addMember('org-id', {
  email: 'newuser@example.com',
  role: 'member',
});

Workspaces

// List all workspaces
const { workspaces } = await client.workspaces.list();

// Create a workspace in an organization
const workspace = await client.workspaces.create('org-id', {
  name: 'Production',
  slug: 'production',
  description: 'Production environment',
});

// Get workspace by ID
const ws = await client.workspaces.get('workspace-id');

// Resolve workspace by slugs (useful for routing)
const ws = await client.workspaces.resolveBySlug('acme-corp', 'production');

// Get workspace statistics
const stats = await client.workspaces.getStats('workspace-id');
console.log(`Objects: ${stats.objectCount}, Records: ${stats.recordCount}`);

File Storage

Upload and manage files within your workspace.

Upload Files

// Upload a file
const file = await client.files.upload(fileBlob, {
  folderId: 'folder-id',  // Optional
});

console.log(`Uploaded: ${file.name} (${file.size} bytes)`);

List Files

// List all files
const { files } = await client.files.list();

// List files in a specific folder
const { files } = await client.files.list('folder-id');

Download Files

// Get a signed download URL
const { url } = await client.files.getDownloadUrl('file-id', 3600); // 1 hour expiry

File Operations

// Rename a file
await client.files.rename('file-id', 'new-name.pdf');

// Move to another folder
await client.files.move('file-id', 'target-folder-id');

// Delete a file
await client.files.delete('file-id');

Folders

// List folders
const { folders } = await client.files.listFolders();

// List subfolders
const { folders } = await client.files.listFolders('parent-folder-id');

// Create a folder
const folder = await client.files.createFolder('Documents', 'parent-folder-id');

// Rename folder
await client.files.renameFolder('folder-id', 'New Name');

// Move folder
await client.files.moveFolder('folder-id', 'new-parent-id');

// Delete folder (and all contents)
await client.files.deleteFolder('folder-id');

Automations

Create automated workflows triggered by record events.

List Automations

const { automations } = await client.automations.list();

Create Automation

const automation = await client.automations.create({
  name: 'Send welcome email',
  description: 'Sends a welcome email when a new contact is created',
  triggerObjectId: 'contacts-object-id',
  triggerType: 'record.created',
  triggerConditions: [
    { field: 'status', operator: 'eq', value: 'active' },
  ],
  actions: [
    {
      type: 'webhook',
      config: {
        url: 'https://api.example.com/send-email',
        method: 'POST',
        headers: { 'Authorization': 'Bearer token' },
        body: '{"email": "{{record.email}}"}',
      },
    },
  ],
});

Automation Triggers

  • record.created - When a new record is created
  • record.updated - When a record is updated
  • record.deleted - When a record is deleted

Automation Actions

  • create_record - Create a record in another object
  • update_record - Update related records
  • delete_record - Delete related records
  • webhook - Call an external webhook

Manage Automations

// Toggle enabled/disabled
await client.automations.toggle('automation-id');

// Update automation
await client.automations.update('automation-id', {
  name: 'Updated name',
  isEnabled: true,
});

// Test execute (for debugging)
const result = await client.automations.execute('automation-id', {
  // Test data matching trigger schema
});

// Delete
await client.automations.delete('automation-id');

AI Conversations

Manage AI chat conversations for building chatbots and assistants.

Create Conversation

const { conversation } = await client.conversations.create({
  title: 'Support Chat',
});

List Conversations

const { conversations, total } = await client.conversations.list({
  limit: 20,
  offset: 0,
});

Add Messages

// Add user message
await client.conversations.addMessage('conversation-id', {
  role: 'user',
  content: 'Hello, I need help!',
});

// Add assistant response
await client.conversations.addMessage('conversation-id', {
  role: 'assistant',
  content: 'Hi! How can I assist you today?',
});

Get Conversation with Messages

const conversation = await client.conversations.get('conversation-id');

for (const message of conversation.messages) {
  console.log(`${message.role}: ${message.content}`);
}

TypeScript Support

The SDK is fully typed. Import types as needed:

import {
  TapstackObject,
  TapstackField,
  TapstackRecord,
  TapstackOrganization,
  TapstackWorkspace,
  TapstackFile,
  FieldType,
  RecordStatus,
  CreateObjectPayload,
  CreateFieldPayload,
  CreateRecordPayload,
} from '@tapstack/db';

Error Handling

The SDK throws AdapterError for API errors:

import { AdapterError } from '@tapstack/db';

try {
  await client.records.get('contacts', 'invalid-id');
} catch (error) {
  if (error instanceof AdapterError) {
    console.error(`Error: ${error.message}`);
    console.error(`Code: ${error.code}`);
    console.error(`Status: ${error.statusCode}`);
    
    if (error.code === 'UNAUTHORIZED') {
      // Handle auth error
    }
  }
}

Custom Adapters

For advanced use cases, you can create a custom adapter:

import { createCustomClient, IInstanceAdapter } from '@tapstack/db';

class MyCustomAdapter implements IInstanceAdapter {
  async request<T>(method: string, path: string, options?: RequestOptions): Promise<T> {
    // Your implementation
  }
  
  async upload<T>(path: string, file: File | Blob, metadata?: Record<string, string>): Promise<T> {
    // Your implementation
  }
  
  setWorkspaceId(id: string | null): void {
    // Your implementation
  }
  
  getWorkspaceId(): string | null {
    // Your implementation
  }
}

const client = createCustomClient(new MyCustomAdapter());

Environment Variables

For Next.js or other frameworks, configure via environment variables:

# .env.local
NEXT_PUBLIC_TAPSTACK_API_URL=https://api.tapstack.com
TAPSTACK_API_KEY=your-api-key
const client = createClient({
  baseUrl: process.env.NEXT_PUBLIC_TAPSTACK_API_URL,
  apiKey: process.env.TAPSTACK_API_KEY,
});

License

MIT

Keywords

tapstack

FAQs

Package last updated on 17 Jan 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts