TailorDB Commands
Commands for managing TailorDB tables, data, and schema migrations.
tailordb
Manage TailorDB tables and data.
Usage
tailor-sdk tailordb [command]Commands
| Command | Description |
|---|---|
tailordb erd | Generate ERD artifacts for TailorDB namespaces using Liam ERD. (beta) |
tailordb migration | Manage TailorDB schema migrations. |
tailordb truncate | Truncate (delete all records from) TailorDB tables. |
tailordb truncate
Truncate (delete all records from) TailorDB tables.
Usage
tailor-sdk tailordb truncate [options] [types]Arguments
| Argument | Description | Required |
|---|---|---|
types | Type names to truncate | No |
Options
| Option | Alias | Description | Required | Default |
|---|---|---|---|---|
--workspace-id <WORKSPACE_ID> | -w | Workspace ID | No | - |
--profile <PROFILE> | -p | Workspace profile | No | - |
--config <CONFIG> | -c | Path to SDK config file | No | "tailor.config.ts" |
--yes | -y | Skip confirmation prompts | No | false |
--all | -a | Truncate all tables in all namespaces | No | false |
--namespace <NAMESPACE> | -n | Truncate all tables in specified namespace | No | - |
tailordb migration
Manage TailorDB schema migrations.
Usage
tailor-sdk tailordb migration [command]Commands
| Command | Description |
|---|---|
tailordb migration generate | Generate migration files by detecting schema differences between current local types and the previous migration snapshot. |
tailordb migration set | Set migration checkpoint to a specific number. |
tailordb migration status | Show the current migration status for TailorDB namespaces, including applied and pending migrations. |
tailordb migration generate
Generate migration files by detecting schema differences between current local types and the previous migration snapshot.
Usage
tailor-sdk tailordb migration generate [options]Options
| Option | Alias | Description | Required | Default |
|---|---|---|---|---|
--yes | -y | Skip confirmation prompts | No | false |
--config <CONFIG> | -c | Path to SDK config file | No | "tailor.config.ts" |
--name <NAME> | -n | Optional description for the migration | No | - |
--init | - | Delete existing migrations and start fresh | No | false |
tailordb migration set
Set migration checkpoint to a specific number.
Usage
tailor-sdk tailordb migration set [options] <number>Arguments
| Argument | Description | Required |
|---|---|---|
number | Migration number to set (e.g., 0001 or 1) | Yes |
Options
| Option | Alias | Description | Required | Default |
|---|---|---|---|---|
--workspace-id <WORKSPACE_ID> | -w | Workspace ID | No | - |
--profile <PROFILE> | -p | Workspace profile | No | - |
--config <CONFIG> | -c | Path to SDK config file | No | "tailor.config.ts" |
--yes | -y | Skip confirmation prompts | No | false |
--namespace <NAMESPACE> | -n | Target TailorDB namespace (required if multiple namespaces exist) | No | - |
tailordb migration status
Show the current migration status for TailorDB namespaces, including applied and pending migrations.
Usage
tailor-sdk tailordb migration status [options]Options
| Option | Alias | Description | Required | Default |
|---|---|---|---|---|
--workspace-id <WORKSPACE_ID> | -w | Workspace ID | No | - |
--profile <PROFILE> | -p | Workspace profile | No | - |
--config <CONFIG> | -c | Path to SDK config file | No | "tailor.config.ts" |
--namespace <NAMESPACE> | -n | Target TailorDB namespace (shows all namespaces if not specified) | No | - |
tailordb erd
Generate ERD artifacts for TailorDB namespaces using Liam ERD. (beta)
Usage
tailor-sdk tailordb erd [command]Commands
| Command | Description |
|---|---|
tailordb erd export | Export Liam ERD dist from applied TailorDB schema. |
tailordb erd serve | Generate and serve ERD locally (liam build + serve dist). (beta) |
tailordb erd deploy | Deploy ERD static website for TailorDB namespace(s). |
tailordb erd export
Export Liam ERD dist from applied TailorDB schema.
Usage
tailor-sdk tailordb erd export [options]Options
| Option | Alias | Description | Required | Default |
|---|---|---|---|---|
--workspace-id <WORKSPACE_ID> | -w | Workspace ID | No | - |
--profile <PROFILE> | -p | Workspace profile | No | - |
--config <CONFIG> | -c | Path to SDK config file | No | "tailor.config.ts" |
--json | -j | Output as JSON | No | false |
--namespace <NAMESPACE> | -n | TailorDB namespace name (optional if only one namespace is defined in config) | No | - |
--output <OUTPUT> | -o | Output directory path for tbls-compatible ERD JSON (writes to <outputDir>/<namespace>/schema.json) | No | ".tailor-sdk/erd" |
tailordb erd serve
Generate and serve ERD locally (liam build + serve dist). (beta)
Usage
tailor-sdk tailordb erd serve [options]Options
| Option | Alias | Description | Required | Default |
|---|---|---|---|---|
--workspace-id <WORKSPACE_ID> | -w | Workspace ID | No | - |
--profile <PROFILE> | -p | Workspace profile | No | - |
--config <CONFIG> | -c | Path to SDK config file | No | "tailor.config.ts" |
--namespace <NAMESPACE> | -n | TailorDB namespace name (uses first namespace in config if not specified) | No | - |
tailordb erd deploy
Deploy ERD static website for TailorDB namespace(s).
Usage
tailor-sdk tailordb erd deploy [options]Options
| Option | Alias | Description | Required | Default |
|---|---|---|---|---|
--workspace-id <WORKSPACE_ID> | -w | Workspace ID | No | - |
--profile <PROFILE> | -p | Workspace profile | No | - |
--config <CONFIG> | -c | Path to SDK config file | No | "tailor.config.ts" |
--json | -j | Output as JSON | No | false |
--namespace <NAMESPACE> | -n | TailorDB namespace name (optional - deploys all namespaces with erdSite if omitted) | No | - |
Usage Examples:
# Truncate all tables in all namespaces (requires confirmation)
tailor-sdk tailordb truncate --all
# Truncate all tables in all namespaces (skip confirmation)
tailor-sdk tailordb truncate --all --yes
# Truncate all tables in a specific namespace
tailor-sdk tailordb truncate --namespace myNamespace
# Truncate specific types (namespace is auto-detected)
tailor-sdk tailordb truncate User Post Comment
# Truncate specific types with confirmation skipped
tailor-sdk tailordb truncate User Post --yesNotes:
- You must specify exactly one of:
--all,--namespace, or type names - When truncating specific types, the namespace is automatically detected from your config
- Confirmation prompts vary based on the operation:
--all: requires typingtruncate all--namespace: requires typingtruncate <namespace-name>- Specific types: requires typing
yes
- Use
--yesflag to skip confirmation prompts (useful for scripts and CI/CD)
Overview
The migration system detects field-level schema differences between your local type definitions and the previous snapshot, then generates migration files to safely apply those changes with data transformations.
Key Features:
- Local snapshot-based diff detection between current types and previous migration snapshot
- Transaction-wrapped data migrations for atomicity - all changes commit or rollback together
- Automatic execution during apply - pending migrations run as part of
tailor-sdk apply - TypeScript migration scripts - type-safe data transformations using Kysely
Usage Examples:
# Generate migration for all schema changes
tailor-sdk tailordb migration generate
# Generate with a description
tailor-sdk tailordb migration generate --name "add email field to user"
# Generate without confirmation prompts
tailor-sdk tailordb migration generate --yes
# Delete existing migrations and start fresh (with confirmation)
tailor-sdk tailordb migration generate --init
# Delete existing migrations and start fresh (skip confirmation)
tailor-sdk tailordb migration generate --init --yesGenerated Files:
Each migration creates a directory in the migrations folder with a 4-digit sequential number:
| File | Description |
|---|---|
0000/schema.json | Initial schema snapshot (first migration only) |
XXXX/diff.json | Schema diff from previous snapshot |
XXXX/migrate.ts | Data migration script (only when breaking changes) |
XXXX/db.ts | Generated Kysely types for the migration script |
Migration Script Structure:
import type { Transaction } from "./db";
export async function main(trx: Transaction): Promise<void> {
// Your data migration logic here
// All operations use the transaction object (trx)
await trx.updateTable("User").set({ newField: "default value" }).execute();
}The db.ts file contains Kysely Transaction types that reflect the schema state before the migration runs. This ensures type-safe data transformations based on the actual database structure at that point in time.
The main function receives a Kysely transaction object. All database operations should use this trx object to ensure atomicity - if any operation fails, all changes are rolled back.
Editor Integration:
If the EDITOR environment variable is set, the generated script file will automatically open in your preferred editor:
export EDITOR=vim
tailor-sdk tailordb migration generate
# → After generation, vim opens XXXX/migrate.tsUsage Examples:
# Set migration checkpoint to 0001 (with confirmation)
tailor-sdk tailordb migration set 1
# Set migration checkpoint without confirmation
tailor-sdk tailordb migration set 1 --yes
# Set for specific namespace
tailor-sdk tailordb migration set 2 --namespace tailordb
# Reset to initial state (all migrations become pending)
tailor-sdk tailordb migration set 0 --yesWarning:
Setting the migration checkpoint changes which migrations will be executed on next apply:
- Forward (e.g., 0001 → 0003): Skips migrations 0002 and 0003
- Backward (e.g., 0003 → 0001): Migrations 0002 and 0003 become pending and will re-execute
The command always displays a warning and requires confirmation unless --yes is specified.
Usage Examples:
# Show status for all namespaces
tailor-sdk tailordb migration status
# Show status for specific namespace
tailor-sdk tailordb migration status --namespace tailordbExample Output:
Namespace: tailordb
Current migration: 0001
Pending migrations:
- 0002: Add email field to user
- 0003: Remove deprecated status fieldConfiguration
Configure migrations in tailor.config.ts:
export default defineConfig({
name: "my-app",
db: {
tailordb: {
files: ["./tailordb/*.ts"],
migration: {
directory: "./migrations",
// Optional: specify machine user for migration script execution
// If not specified, the first machine user from auth.machineUsers is used
machineUser: "admin-machine-user",
},
},
},
});Configuration Options
| Option | Type | Description |
|---|---|---|
files | string[] | Glob patterns for TailorDB type definition files |
ignores | string[] | Glob patterns to ignore |
migration.directory | string | Directory path for migration files |
migration.machineUser | string | Machine user name for migration script execution (optional, defaults to first machine user from auth.machineUsers) |
Machine User Selection
When executing migration scripts, the system selects a machine user in the following priority:
- Explicit configuration:
migration.machineUserin db config - Auto-selection: First machine user from
auth.machineUsers
The machine user being used is logged during migration execution.
Migration Directory Structure
Migrations use a directory-based structure with 4-digit sequential numbering:
migrations/
├── 0000/ # Initial schema (number 0)
│ └── schema.json # Full schema snapshot
├── 0001/ # First change
│ ├── diff.json # Schema diff
│ ├── migrate.ts # Migration script (if breaking changes)
│ └── db.ts # Kysely types (if breaking changes)
├── 0002/ # Second change
│ └── diff.json
└── ...0000- Initial schema snapshot (always starts at 0)0001- First schema change0002- Second schema change, etc.
Supported Schema Changes
| Change Type | Breaking? | Migration Script | Notes |
|---|---|---|---|
| Add optional field | No | No | Schema change only |
| Add required field | Yes | Yes | Script populates default values |
| Remove field | No | No | Schema change only - data is preserved |
| Change optional→required | Yes | Yes | Script sets defaults for null values |
| Change required→optional | No | No | Schema change only |
| Add index | No | No | Schema change only |
| Remove index | No | No | Schema change only |
| Add unique constraint | Yes | Yes | Script must resolve duplicate values |
| Remove unique constraint | No | No | Schema change only |
| Add enum value | No | No | Schema change only |
| Remove enum value | Yes | Yes | Script migrates records with removed values |
| Add type | No | No | Schema change only |
| Remove type | No | No | Schema change only - data is preserved |
| Change field type | - | - | Not supported - requires 3-step migration |
| Change array to single value | - | - | Not supported - requires 3-step migration |
| Change single value to array | - | - | Not supported - requires 3-step migration |
| Change foreign key relationship | Yes | Yes | Script updates existing references |
Unsupported Schema Changes
The following changes require a 3-step migration process:
Field Type Change
Field type changes (e.g., string → integer) are not directly supported. Use this migration strategy:
- Migration 1: Add a new field with the desired type (e.g.,
fieldName_new) and migrate data - Migration 2: Remove the old field
- Migration 3: Add the field with the original name and new type, migrate data from temporary field, then remove temporary field
Array Property Change
Changing between single value and array (e.g., array: false → array: true) is not directly supported. Use the same 3-step migration strategy as field type changes.
Example Workflow
Modify your type definition:
typescript// tailordb/user.ts export const user = db.type("User", { name: db.string(), email: db.string(), // ← New required field ...db.fields.timestamps(), });Generate migration:
bashtailor-sdk tailordb migration generate # Output: Generated migration 0001 # Diff file: ./migrations/0001/diff.json # Migration script: ./migrations/0001/migrate.ts # DB types: ./migrations/0001/db.tsEdit the migration script (
0001/migrate.ts):typescriptimport type { Transaction } from "./db"; export async function main(trx: Transaction): Promise<void> { await trx .updateTable("User") .set({ email: "default@example.com" }) .where("email", "is", null) .execute(); }Apply migration:
bashtailor-sdk apply # Migrations are automatically executed during apply
Automatic Migration Execution
When running tailor-sdk apply, pending migration scripts are automatically executed as part of the deployment process.
How It Works
- Pending Migration Detection: Identifies migration scripts that haven't been executed yet
- Two-Stage Type Update: For breaking changes (required fields, type changes):
- Pre-Migration: New fields are added as
optionalfirst - Script Execution: Migration scripts run to populate data
- Post-Migration: Fields are changed to
required, deletions are applied
- Pre-Migration: New fields are added as
Execution Flow
tailor-sdk apply
│
├── Detect Pending Migrations
│
├── [If pending migrations exist]
│ ├── Pre-Migration: Add fields as optional
│ ├── Execute Migration Scripts (TestExecScript API)
│ └── Post-Migration: Apply required, deletions
│
└── Continue with normal apply flowRequirements for Automatic Migration
- Migrations configured:
migrationspath set in db config - Auth configured: Auth service with machine users
- Kysely generator:
@tailor-platform/kysely-typegenerator configured
Schema Verification
By default, tailor-sdk apply performs two schema verifications:
- Local schema check: Ensures local type definitions match the migration snapshot
- Remote schema check: Ensures remote schema matches the expected state based on migration history
If remote schema drift is detected, you'll see an error like:
✖ Remote schema drift detected:
Namespace: tailordb
Remote migration: 0007
Differences:
Type 'User':
- Field 'email': required: remote=false, expected=true
ℹ This may indicate:
- Another developer applied different migrations
- Manual schema changes were made directly
- Migration history is out of sync
ℹ Use '--no-schema-check' to skip this check (not recommended).Skipping Schema Check
To skip both local and remote schema verification (not recommended for production):
tailor-sdk apply --no-schema-checkWarning: Skipping schema checks may result in applying migrations to an inconsistent state.
Example Output
ℹ Found 2 pending migration(s) to execute.
ℹ Executing 2 pending migration(s)...
ℹ Using machine user: admin-machine-user
✔ Migration tailordb/0002 completed successfully
✔ Migration tailordb/0003 completed successfully
✔ All migrations completed successfully.
✔ Successfully applied changes.Troubleshooting
Remote schema drift detected
Cause: The remote schema doesn't match the expected state based on migration history. This can happen when:
- Another developer applied different migrations
- Schema was changed manually outside of migrations
- Migration history is out of sync
Solution:
- Check migration status: Run
tailor-sdk tailordb migration statusto see current state - Sync with team: Ensure all team members have the same migration files
- Reset if needed: Use
tailor-sdk tailordb migration set <number>to reset migration checkpoint - Force apply (use with caution): Use
--no-schema-checkto skip verification
"Machine user not found"
Cause: Specified machine user doesn't exist in auth configuration.
Solution:
- Check available users: The error message lists available machine users
- Add machine user to your auth config:typescript
machineUsers: { "your-user-name": { attributes: { role: "ADMIN" }, }, } - Run
tailor-sdk applyto deploy the auth config - Retry migration
Migration script execution fails
Cause: Runtime error in your data migration logic.
Solution:
- Check the error message for the failing query/operation
- Test your script logic locally if possible
- Fix the script
- Apply again:
tailor-sdk apply
Notes:
- This command is a beta feature and may introduce breaking changes in future releases
Usage Examples:
# Deploy ERD for all namespaces with erdSite configured
tailor-sdk tailordb erd deploy
# Deploy ERD for a specific namespace
tailor-sdk tailordb erd deploy --namespace myNamespace
# Deploy ERD with JSON output
tailor-sdk tailordb erd deploy --jsonNotes:
- Requires
erdSiteto be configured intailor.config.tsfor each namespace you want to deploy - Example config:typescript
export default defineConfig({ db: { myNamespace: { // ... table definitions erdSite: "my-erd-site-name", }, }, });