Getting Started Guide

Comprehensive step-by-step guide to building production-ready APIs with DataBridge - includes testing, logging, and error handling

Getting Started with DataBridge

Last Updated: January 5, 2026
Version: 0.2.9
Status: Living Document - Updated Regularly

What is DataBridge? A powerful CLI tool that automatically generates production-ready APIs and frontend SDKs from your existing database. Now supports 5 databases: MySQL, PostgreSQL, SQL Server, SQLite, and CockroachDB. Features built-in Zod validation, comprehensive error handling, production logging, Prisma 7 adapters, and automated testing. No boilerplate, no repetitive coding - just point it at your database and start building.

Prerequisites

Before you begin, ensure you have:

  • Node.js 18+ installed (Download)
  • Database - One of the following:
    • MySQL 8.0+
    • PostgreSQL 13+
    • SQL Server 2019+
    • SQLite 3+
    • CockroachDB 22+
  • pnpm package manager (npm install -g pnpm)
  • Basic knowledge of TypeScript and Angular/React
  • 10 minutes of your time

Quick Start (5 Minutes)

Step 1: Create Your Project

# Create a new directory for your project
mkdir my-databridge-app
cd my-databridge-app

# Initialize npm project
npm init -y

Step 2: Install DataBridge CLI

Install the universal package (works on all platforms):

npm install -g @databridge-cli/cli

# Verify installation
databridge --version

Step 3: Initialize DataBridge

# Run the init command
databridge init

The CLI will ask you:

  1. Database Provider - Choose your database type

    Options: MySQL, PostgreSQL, SQL Server, SQLite, CockroachDB
  2. Database URL - Your database connection string

    MySQL:       mysql://root:password@localhost:3306/mydb
    PostgreSQL:  postgresql://postgres:password@localhost:5432/mydb
    SQL Server:  sqlserver://localhost:1433;database=mydb;user=sa;password=Pass123!
    SQLite:      file:./dev.db
    CockroachDB: postgresql://root@localhost:26257/mydb?sslmode=disable

    SQL Server Note: After init, you must manually add these environment variables to .env:

    DB_SERVER=127.0.0.1
    DB_PORT=1433
    DB_NAME=mydb
    DB_USER=sa
    DB_PASSWORD=YourStrong@Passw0rd
  3. API Output Path - Where to generate backend routes

    Default: api
  4. Frontend Output Path - Where to generate Angular services

    Default: src/app/databridge
  5. API Port - Port for your API server

    Default: 3000

Result: Creates .databridge.json configuration file

Step 4: Introspect Your Database

databridge introspect

This command will:

  • Auto-detect database provider from your connection string ⭐ NEW
  • Update schema.prisma with correct provider ⭐ NEW
  • ✅ Connect to your database (MySQL, PostgreSQL, SQL Server, SQLite, or CockroachDB)
  • ✅ Read all tables, columns, and relationships
  • ✅ Generate or update prisma/schema.prisma file
  • ✅ Install Prisma dependencies and adapters automatically ⭐ NEW

Example Output:

Introspecting database...
✓ Connected to mysql://localhost:3306/mydb
✓ Found 4 tables: users, products, orders, order_items

Database Schema:
  • users (4 columns)
  • products (9 columns)
  • orders (7 columns)
  • order_items (6 columns)

✅ Introspection complete!
Generated: prisma/schema.prisma

Step 5: Generate API & SDK

databridge generate

This command generates:

  • OpenAPI 3.0 Specification (src/openapi.json)
  • Swagger UI Plugin (src/plugins/swagger.ts)
  • Fastify API routes with CRUD operations and Zod validation
  • Prisma plugin - Automatically created and configured
  • Prisma Client - Generated automatically
  • Comprehensive error handling (400, 404, 409, 500 status codes)
  • Production-ready Pino logger with structured JSON logs
  • Automated test suite (bash script with 14+ tests)
  • Health & metrics endpoints for monitoring
  • Angular services with HttpClient
  • TypeScript interfaces for type safety
  • Bundled dependencies - Zero npm install required!

Example Output:

⚙️  Generating code from Prisma schema...

Found 4 models

  Generating API route: users.ts
  Generating API route: products.ts
  Generating API route: orders.ts
  Generating API route: order_items.ts
  Generating Angular service: usersService
  Generating Angular service: productsService
  Generating Angular service: ordersService
  Generating Angular service: order_itemsService
  Generated TypeScript models: models/index.ts
  Generated test script: test-api.sh
  Generated logger utility: utils/logger.ts
  Generated server: server.ts

✅ Code generation complete!

Generated:
  API routes:      api/routes/
  Angular services: src/app/databridge/services/
  TypeScript models: src/app/databridge/models/
  Logger utility:  api/utils/logger.ts
  Test script:      test-api.sh

Step 6: Start Your API Server

The server automatically finds an available port (tries 3000-3004):

# Navigate to your generated API directory
cd apps/api

# Start the development server
npm run dev

Your API is now running at http://localhost:3000 (or the next available port)!

Server includes:

  • /docs - Interactive Swagger UI for API testing
  • /openapi.json - Downloadable OpenAPI 3.0 specification
  • /health - Health check with database connectivity
  • /metrics - Memory usage and uptime statistics
  • ✅ Request correlation IDs for log tracking
  • ✅ Graceful shutdown handling

Step 7: Run Automated Tests

# Go back to project root
cd ../..

# Run the auto-generated test suite
bash test-api.sh

Example Output:

=========================================
DataBridge API Test Suite
=========================================

Test: Health Check
✅ Pass

Test: GET /users (List all)
✅ Pass

Test: POST /users (Create valid)
✅ Pass

Test: POST /users (Missing required field)
✅ Pass - Validation caught missing field

Test: POST /products (Negative price)
✅ Pass - Validation caught negative price

... (9 more tests)

=========================================
Test Suite Complete: 14/14 passed
=========================================

Step 9: Generate Client SDKs (Optional)

Generate type-safe client SDKs in any language:

# Python SDK
databridge generate-sdk --lang python

# Go SDK
databridge generate-sdk --lang go

# Multiple languages
databridge generate-sdk --lang python,go,csharp,typescript

Generated SDKs include:

  • ✅ Full type safety
  • ✅ All CRUD operations
  • ✅ Request validation
  • ✅ Error handling
  • ✅ Usage documentation

Learn more: Multi-Language SDK Generation

Step 10: Test Error Handling

# Invalid ID format (400)
curl http://localhost:3000/users/abc
# {"error":"Invalid ID format","message":"ID must be a number"}

# Record not found (404)
curl http://localhost:3000/users/99999
# {"error":"users not found"}

# Validation error (400)
curl -X POST http://localhost:3000/products \
  -H "Content-Type: application/json" \
  -d '{"name":"","price":-10}'
# {"error":"Validation failed","details":[...]}

Complete Tutorial

Understanding the Configuration File

After running databridge init, you’ll have a .databridge.json file:

{
  "version": "0.2.9",
  "database": {
    "url": "mysql://root:password@localhost:3306/mydb"
  },
  "api": {
    "outputPath": "api",
    "port": 3000,
    "cors": "*"
  },
  "angular": {
    "outputPath": "src/app/databridge"
  },
  "auth": {
    "jwtSecret": "your-generated-secret-key"
  }
}

Multi-Database Examples:

MySQL:

{
  "version": "0.2.9",
  "database": {
    "url": "mysql://root:password@localhost:3306/mydb"
  }
}

PostgreSQL:

{
  "version": "0.2.9",
  "database": {
    "url": "postgresql://postgres:password@localhost:5432/mydb"
  }
}

SQL Server:

{
  "version": "0.2.9",
  "database": {
    "url": "sqlserver://localhost:1433;database=mydb;user=sa;password=YourStrong@Passw0rd;encrypt=true;trustServerCertificate=true"
  }
}

SQLite:

{
  "version": "0.2.9",
  "database": {
    "url": "file:./dev.db"
  }
}

CockroachDB:

{
  "version": "0.2.9",
  "database": {
    "url": "postgresql://root@localhost:26257/mydb?sslmode=disable"
  }
}
"cors": "*"

}, “angular”: { “outputPath”: “src/app/databridge” }, “auth”: { “jwtSecret”: “your-generated-secret-key” } }


**Configuration Options**:

| Field | Description | Default |
|-------|-------------|---------|
| `database.url` | Database connection string (MySQL, PostgreSQL, SQL Server, SQLite, CockroachDB) | Required |
| `api.outputPath` | Where to generate API routes | `api` |
| `api.port` | API server port | `3000` |
| `api.cors` | CORS origin configuration | `*` (all origins) |
| `angular.outputPath` | Where to generate Angular services | `src/app/databridge` |
| `auth.jwtSecret` | JWT secret for authentication | Auto-generated |

### Understanding Prisma Schema

After `databridge introspect`, your `prisma/schema.prisma` looks like:

**MySQL Example:**
```prisma
generator client {
  provider = "prisma-client-js"
  output   = "../generated/prisma"
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

model products {
  id          Int       @id @default(autoincrement())
  name        String    @db.VarChar(255)
  description String?   @db.Text
  price       Decimal   @db.Decimal(10, 2)
  stock       Int?      @default(0)
  category    String?   @db.VarChar(100)
  is_active   Boolean?  @default(true)
  created_at  DateTime? @default(now())
  updated_at  DateTime? @default(now())
}

PostgreSQL Example:

generator client {
  provider = "prisma-client-js"
  output   = "../generated/prisma"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model products {
  id          Int       @id @default(autoincrement())
  name        String    @db.VarChar(255)
  description String?
  price       Decimal   @db.Decimal(10, 2)
  stock       Int?      @default(0)
  created_at  DateTime? @default(now()) @db.Timestamptz(6)
}

SQL Server Example:

generator client {
  provider = "prisma-client-js"
  output   = "../generated/prisma"
}

datasource db {
  provider = "sqlserver"
  url      = env("DATABASE_URL")
}

model products {
  id          Int       @id @default(autoincrement())
  name        String    @db.NVarChar(255)
  description String?   @db.NVarChar(Max)
  price       Decimal   @db.Decimal(10, 2)
  stock       Int?      @default(0)
  created_at  DateTime? @default(now()) @db.DateTime
}

New in v0.2.x: The provider field is automatically detected and set during databridge introspect!

Key Concepts:

  • @id: Primary key field
  • @default(autoincrement()): Auto-incrementing ID
  • @db.VarChar(255): Database-specific column type
  • ?: Optional/nullable field
  • @relation: Foreign key relationship
  • output: Prisma 7 requires explicit output path for generated client

Generated API Routes

For each model, DataBridge generates a complete CRUD API:

File: api/routes/products.ts

import { FastifyInstance, FastifyRequest, FastifyReply } from "fastify";
import { prisma } from "../plugins/prisma";

export default async function productsRoutes(fastify: FastifyInstance) {
  // GET /products - List all products
  fastify.get('/products', async (request: FastifyRequest, reply: FastifyReply) => {
    const items = await prisma.products.findMany();
    return reply.send(items);
  });

  // GET /products/:id - Get one product
  fastify.get<{ Params: { id: string } }>('/products/:id', async (request, reply) => {
    const id = parseInt(request.params.id);
    const item = await prisma.products.findUnique({ where: { id } });
    
    if (!item) {
      return reply.status(404).send({ error: 'products not found' });
    }
    
    return reply.send(item);
  });

  // POST /products - Create product
  fastify.post('/products', async (request: FastifyRequest, reply: FastifyReply) => {
    const item = await prisma.products.create({
      data: request.body as any,
    });
    return reply.status(201).send(item);
  });

  // PATCH /products/:id - Update product
  fastify.patch<{ Params: { id: string } }>('/products/:id', async (request, reply) => {
    const id = parseInt(request.params.id);
    const item = await prisma.products.update({
      where: { id },
      data: request.body as any,
    });
    return reply.send(item);
  });

  // DELETE /products/:id - Delete product
  fastify.delete<{ Params: { id: string } }>('/products/:id', async (request, reply) => {
    const id = parseInt(request.params.id);
    await prisma.products.delete({ where: { id } });
    return reply.status(204).send();
  });
}

Generated Angular Services

File: src/app/databridge/services/products.service.ts

import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Observable } from "rxjs";
import { products } from "../models";

@Injectable({ providedIn: 'root' })
export class ProductsService {
  constructor(private http: HttpClient) {}

  private apiUrl = 'http://localhost:3000/products';

  list(): Observable<products[]> {
    return this.http.get<products[]>(this.apiUrl);
  }

  getById(id: number): Observable<products> {
    return this.http.get<products>(`${this.apiUrl}/${id}`);
  }

  create(data: Partial<products>): Observable<products> {
    return this.http.post<products>(this.apiUrl, data);
  }

  update(id: number, data: Partial<products>): Observable<products> {
    return this.http.patch<products>(`${this.apiUrl}/${id}`, data);
  }

  delete(id: number): Observable<void> {
    return this.http.delete<void>(`${this.apiUrl}/${id}`);
  }
}

Using the Generated Services in Angular

import { Component, OnInit } from '@angular/core';
import { ProductsService } from './databridge/services/products.service';
import { products } from './databridge/models';

@Component({
  selector: 'app-products',
  template: `
    <div *ngFor="let product of products">
      <h3>{{ product.name }}</h3>
      <p>{{ product.description }}</p>
      <p>Price: ${{ product.price }}</p>
    </div>
  `
})
export class ProductsComponent implements OnInit {
  products: products[] = [];

  constructor(private productsService: ProductsService) {}

  ngOnInit() {
    // Get all products
    this.productsService.list().subscribe(
      data => this.products = data
    );
  }

  createProduct() {
    // Create new product
    this.productsService.create({
      name: 'New Product',
      price: 99.99,
      stock: 10
    }).subscribe(
      created => console.log('Created:', created)
    );
  }
}

Advanced Usage

Custom Server Setup

Create api/server.ts:

import Fastify from 'fastify';
import cors from '@fastify/cors';
import productsRoutes from './routes/products';
import usersRoutes from './routes/users';
import prismaPlugin from './plugins/prisma';

async function start() {
  const fastify = Fastify({
    logger: {
      transport: {
        target: 'pino-pretty',
        options: {
          translateTime: 'HH:MM:ss',
          ignore: 'pid,hostname',
        },
      },
    },
  });

  // Register plugins
  await fastify.register(cors, { origin: '*' });
  await fastify.register(prismaPlugin);

  // Register routes
  await fastify.register(productsRoutes);
  await fastify.register(usersRoutes);

  // Health check
  fastify.get('/health', async () => {
    return { status: 'ok', timestamp: new Date().toISOString() };
  });

  // Start server
  await fastify.listen({ port: 3000, host: '0.0.0.0' });
  console.log('Server running on http://localhost:3000');
}

start();

Run with:

npx tsx api/server.ts

Environment Variables

Create .env file:

DATABASE_URL="mysql://root:password@localhost:3306/mydb"
JWT_SECRET="your-secret-key"
API_PORT=3000
NODE_ENV=development

Update .databridge.json to use env vars:

{
  "database": {
    "url": "${DATABASE_URL}"
  },
  "api": {
    "port": "${API_PORT}"
  }
}

Docker Setup

Using Docker for MySQL:

docker run -d \
  --name mysql-db \
  -e MYSQL_ROOT_PASSWORD=password \
  -e MYSQL_DATABASE=mydb \
  -p 3306:3306 \
  mysql:8.0

Or use docker-compose.yml:

services:
  mysql:
    image: mysql:8.0
    container_name: databridge-mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: mydb
    ports:
      - "3306:3306"
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  mysql_data:

Real-World Example

Complete E-commerce Setup

1. Database Schema (schema.sql):

CREATE TABLE users (
  id INT PRIMARY KEY AUTO_INCREMENT,
  email VARCHAR(255) UNIQUE NOT NULL,
  name VARCHAR(100) NOT NULL,
  role ENUM('admin', 'user', 'guest') DEFAULT 'user',
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE products (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(255) NOT NULL,
  description TEXT,
  price DECIMAL(10, 2) NOT NULL,
  stock INT DEFAULT 0,
  category VARCHAR(100),
  is_active BOOLEAN DEFAULT true,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE orders (
  id INT PRIMARY KEY AUTO_INCREMENT,
  user_id INT NOT NULL,
  total DECIMAL(10, 2) NOT NULL,
  status ENUM('pending', 'paid', 'shipped', 'delivered') DEFAULT 'pending',
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

CREATE TABLE order_items (
  id INT PRIMARY KEY AUTO_INCREMENT,
  order_id INT NOT NULL,
  product_id INT NOT NULL,
  quantity INT DEFAULT 1,
  price DECIMAL(10, 2) NOT NULL,
  FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE,
  FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE
);

2. Load Schema:

mysql -u root -p mydb < schema.sql

3. Initialize DataBridge:

databridge init
# Enter: mysql://root:password@localhost:3306/mydb

4. Introspect & Generate:

databridge introspect
databridge generate

5. Start Server & Test:

npx tsx api/server.ts

# Test endpoints
curl http://localhost:3000/users
curl http://localhost:3000/products
curl http://localhost:3000/orders

Result: Full-featured e-commerce API in under 5 minutes!

Testing Your API

DataBridge automatically generates a comprehensive test suite for your API. This ensures your validation rules, CRUD operations, and constraints work correctly.

Automatic Test Generation

When you run databridge generate, a test-api.sh script is created with tests for:

  • Health check endpoint
  • List operations (GET /model)
  • Create operations (POST /model) with valid data
  • Validation tests for required fields
  • Validation tests for empty strings
  • Validation tests for negative numbers (prices, quantities)
  • Validation tests for constraint violations

Running Tests

# Start your API server first
npx tsx api/server.ts

# In another terminal, run the test suite
./test-api.sh

Example Test Output

=========================================
DataBridge API Test Suite
Generated: 2025-11-20T08:02:49.495Z
=========================================

Test: Health Check
{"status":"ok","timestamp":"2025-11-20T08:03:39.090Z"}
 Pass

# ========== Products Tests ==========

Test: GET /products (List all)
[{"id":1,"name":"Laptop Pro","price":"1299.99",...}]
 Pass

Test: POST /products (Create valid)
{"id":19,"name":"Test products","price":"99.99",...}
 Pass

Test: POST /products (Missing required field)
 Pass - Validation caught missing field

Test: POST /products (Empty name)
 Pass - Validation caught empty string

Test: POST /products (Negative price)
 Pass - Validation caught negative price

=========================================
Test Suite Complete
=========================================

What Gets Tested

For each model in your schema, the test suite validates:

1. Required Fields

# Missing 'name' field
curl -X POST http://localhost:3000/products \
  -H "Content-Type: application/json" \
  -d '{}'

# Response:
{
  "error": "Validation failed",
  "issues": [
    {
      "path": ["name"],
      "message": "Required"
    }
  ]
}

2. String Constraints

# Empty string for required field
curl -X POST http://localhost:3000/products \
  -H "Content-Type: application/json" \
  -d '{"name": ""}'

# Response:
{
  "error": "Validation failed",
  "issues": [
    {
      "path": ["name"],
      "message": "Cannot be empty"
    }
  ]
}

3. Number Constraints

# Negative price (should be positive)
curl -X POST http://localhost:3000/products \
  -H "Content-Type: application/json" \
  -d '{"price": -10}'

# Response:
{
  "error": "Validation failed",
  "issues": [
    {
      "path": ["price"],
      "message": "Price must be greater than 0"
    }
  ]
}

4. Custom Constraints

# Negative stock (should be non-negative)
curl -X POST http://localhost:3000/products \
  -H "Content-Type: application/json" \
  -d '{"stock": -5}'

# Response:
{
  "error": "Validation failed",
  "issues": [
    {
      "path": ["stock"],
      "message": "Stock cannot be negative"
    }
  ]
}

Customizing Tests

The generated test script is a bash file you can modify:

#!/bin/bash

# Add custom tests
echo "Test: Custom validation"
RESPONSE=$(curl -s -X POST http://localhost:3000/products \
  -H "Content-Type: application/json" \
  -d '{"name": "Test", "price": 0}')

if echo "$RESPONSE" | grep -q "Validation failed"; then
  echo "✅ Pass - Zero price rejected"
else
  echo "❌ Fail - Should reject zero price"
fi

CI/CD Integration

Add to your GitHub Actions workflow:

name: API Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    
    services:
      mysql:
        image: mysql:8.0
        env:
          MYSQL_ROOT_PASSWORD: password
          MYSQL_DATABASE: testdb
        ports:
          - 3306:3306
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '20'
      
      - name: Install dependencies
        run: pnpm install
      
      - name: Start API server
        run: npx tsx api/server.ts &
        
      - name: Wait for server
        run: sleep 5
      
      - name: Run tests
        run: ./test-api.sh

Test Coverage

The auto-generated tests provide:

  • Schema validation - All Zod constraints tested
  • CRUD operations - List and create tested for each model
  • Error handling - 400 Bad Request with detailed errors
  • Type safety - String, number, boolean validations
  • Business rules - Price positivity, stock non-negativity

Manual Testing with cURL

For ad-hoc testing:

# Create a product
curl -X POST http://localhost:3000/products \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Mechanical Keyboard",
    "price": 129.99,
    "stock": 50
  }'

# Get all products
curl http://localhost:3000/products

# Update a product
curl -X PATCH http://localhost:3000/products/1 \
  -H "Content-Type: application/json" \
  -d '{"stock": 45}'

# Delete a product
curl -X DELETE http://localhost:3000/products/1

Testing Best Practices

  1. Run tests after every generation

    databridge generate && ./test-api.sh
  2. Check test output carefully

    • All tests should show ✅ Pass
    • Validation errors should return 400 status
    • Success operations should return 200/201 status
  3. Test edge cases manually

    • Very large numbers
    • Unicode characters in strings
    • JSON injection attempts
    • SQL injection attempts (Prisma prevents this)
  4. Monitor API logs

    • Check for unexpected errors
    • Verify validation messages are clear
    • Ensure sensitive data isn’t logged

Troubleshooting

Common Issues

1. “No models found” after generate

Cause: Wrong working directory
Solution: Always run commands from your project root:

# ❌ Wrong
pnpm --dir ../packages/cli dev generate

# ✅ Correct
cd my-project
../path/to/cli/bin/dev.ts generate

2. Prisma version mismatch

Error: Module not found: @prisma/client
Solution: Ensure consistent Prisma version:

pnpm add prisma@5.22.0 @prisma/client@5.22.0

3. TypeScript import errors

Error: Unknown file extension ".ts"
Solution: Use tsx to run TypeScript files:

npx tsx api/server.ts

4. Database connection refused

Error: Can't reach database server
Solution: Check MySQL is running:

# Check MySQL status
docker ps | grep mysql

# Or for local MySQL
systemctl status mysql

5. Port already in use

Error: EADDRINUSE: address already in use
Solution: Kill process or use different port:

# Find process
lsof -i :3000

# Kill it
kill -9 <PID>

# Or change port in .databridge.json

Performance Tips

1. Use Query Optimization

// ❌ N+1 Query Problem
const users = await prisma.users.findMany();
for (const user of users) {
  const orders = await prisma.orders.findMany({
    where: { user_id: user.id }
  });
}

// ✅ Use include
const users = await prisma.users.findMany({
  include: { orders: true }
});

2. Add Pagination

fastify.get('/products', async (request) => {
  const { page = 1, limit = 10 } = request.query as any;
  
  const products = await prisma.products.findMany({
    skip: (page - 1) * limit,
    take: limit,
  });
  
  return products;
});

3. Add Caching

import { FastifyCachingPlugin } from '@fastify/caching';

await fastify.register(FastifyCachingPlugin, {
  privacy: 'public',
  expiresIn: 60, // 60 seconds
});

Security Best Practices

1. Use Environment Variables

Never commit .databridge.json with credentials:

# Add to .gitignore
.databridge.json
.env

2. Add Input Validation

Option A: Using Zod (Recommended)

pnpm add zod @fastify/type-provider-zod
import { z } from 'zod';
import { 
  serializerCompiler, 
  validatorCompiler 
} from '@fastify/type-provider-zod';

// Set up Zod for Fastify
fastify.setValidatorCompiler(validatorCompiler);
fastify.setSerializerCompiler(serializerCompiler);

// Define schema with Zod
const createProductSchema = z.object({
  name: z.string().min(1).max(255),
  description: z.string().optional(),
  price: z.number().positive(),
  stock: z.number().int().nonnegative().default(0),
  category: z.string().max(100).optional(),
});

// Use schema in route with automatic type inference
fastify.post('/products', {
  schema: {
    body: createProductSchema,
  }
}, async (request, reply) => {
  // request.body is now fully typed!
  const item = await prisma.products.create({
    data: request.body,
  });
  return reply.status(201).send(item);
});

// Get better error messages automatically
// POST with invalid data returns:
// {
//   "statusCode": 400,
//   "error": "Bad Request",
//   "message": "body/price: Expected number, received string"
// }

Option B: Using TypeBox (Faster, if performance critical)

pnpm add @sinclair/typebox
import { Type } from '@sinclair/typebox';

fastify.post('/products', {
  schema: {
    body: Type.Object({
      name: Type.String({ minLength: 1, maxLength: 255 }),
      price: Type.Number({ minimum: 0 }),
      stock: Type.Optional(Type.Integer({ minimum: 0 })),
    })
  }
}, async (request, reply) => {
  const item = await prisma.products.create({
    data: request.body as any,
  });
  return reply.status(201).send(item);
});

When to use each:

  • Zod: Better DX, type inference, most projects (recommended)
  • TypeBox: High-performance APIs (>10k req/s), need JSON Schema

3. Add Authentication

import jwt from '@fastify/jwt';

await fastify.register(jwt, {
  secret: process.env.JWT_SECRET || 'your-secret'
});

// Protected route
fastify.get('/products', {
  onRequest: [fastify.authenticate]
}, async (request, reply) => {
  // Only authenticated users can access
  const products = await prisma.products.findMany();
  return products;
});

Learning Path

Beginner

  1. ✅ Complete Quick Start guide
  2. ✅ Understand Prisma schema basics
  3. ✅ Test all CRUD endpoints
  4. ✅ Integrate with simple Angular app

Intermediate

  1. Add custom routes beyond CRUD
  2. Implement authentication & authorization
  3. Add request validation
  4. Set up production deployment

Advanced

  1. Custom code generation templates
  2. Multi-database support
  3. Real-time subscriptions with WebSockets
  4. Contribute to DataBridge core

Additional Resources

Contributing

Found a bug or want to improve this guide?

Changelog

Version 0.1.0 (November 19, 2025)

  • ✅ Initial CLI with 4 commands (init, introspect, generate, serve)
  • ✅ MySQL introspection support
  • ✅ Fastify API route generation
  • ✅ Angular service generation
  • ✅ TypeScript model generation
  • ✅ CRUD operations for all models
  • ✅ Prisma integration

Coming Soon

  • 🔜 React SDK generation
  • 🔜 Vue SDK generation
  • 🔜 PostgreSQL support
  • 🔜 MongoDB support
  • 🔜 Authentication scaffolding
  • 🔜 GraphQL API generation
  • 🔜 Real-time WebSocket support

Recently Added ⭐

  • OpenAPI 3.0 Specification - Auto-generated from Prisma schema
  • Interactive Swagger UI - Test APIs at /docs endpoint
  • Multi-Language SDK Generation - 50+ languages (Python, Go, C#, Java, etc.)
  • Testing Ecosystem - Dredd contract testing, Prism mock servers

Learn more: API Tutorials


Was this page helpful?