Overview
The@databite/build
package provides the core functionality for creating connectors using a fluent API. It includes the ConnectorBuilder class, action and sync creators, and helper functions for building type-safe connectors.
Installation
Copy
Ask AI
npm install @databite/build @databite/types @databite/flow
Copy
Ask AI
npm install zod typescript
Core Classes
ConnectorBuilder
The main class for building connectors with a fluent API:Copy
Ask AI
import { createConnector } from "@databite/build";
import { z } from "zod";
const connector = createConnector()
.withIdentity("my-service", "My Service")
.withVersion("1.0.0")
.withAuthor("Your Name")
.withLogo("https://example.com/logo.png")
.withDescription("Connector for My Service")
.build();
Builder Methods
Identity & Metadata
Copy
Ask AI
// Set connector identity
.withIdentity(id: string, name: string)
// Set version
.withVersion(version: string)
// Set author
.withAuthor(author: string)
// Set logo URL
.withLogo(logo: string)
// Set documentation URL
.withDocumentationUrl(url: string)
// Set description
.withDescription(description: string)
Configuration
Copy
Ask AI
// Add integration configuration schema
.withIntegrationConfig(config: ZodSchema)
// Add connection configuration schema
.withConnectionConfig(config: ZodSchema)
// Add tags for categorization
.withTags(...tags: string[])
// Add categories
.withCategories(...categories: ConnectorCategory[])
Flows
Copy
Ask AI
// Set authentication flow
.withAuthenticationFlow(flow: Flow<TConnectionConfig>)
// Set refresh function
.withRefresh(refresh: (connection: Connection<TConnectionConfig>) => Promise<z.infer<TConnectionConfig>>)
Actions & Syncs
Copy
Ask AI
// Add actions
.withActions(actions: Record<string, Action>)
// Add syncs
.withSyncs(syncs: Record<string, Sync>)
Helper Functions
createAction
Creates an action with automatic retry logic and timeout handling:Copy
Ask AI
import { createAction } from "@databite/build";
import { z } from "zod";
const action = createAction({
label: "Get User",
description: "Fetch user by ID",
inputSchema: z.object({ id: z.string() }),
outputSchema: z.object({
user: z.object({ id: z.string(), name: z.string() }),
}),
maxRetries: 3,
timeout: 30000,
handler: async (params, connection) => {
// Your implementation
return { user: { id: params.id, name: "John Doe" } };
},
});
createSync
Creates a sync operation for data synchronization:Copy
Ask AI
import { createSync } from "@databite/build";
const sync = createSync({
label: "Sync Users",
description: "Synchronize user data",
schedule: "0 9 * * *", // Daily at 9 AM
outputSchema: z.array(z.object({ id: z.string() })),
maxRetries: 3,
timeout: 60000,
handler: async (connection) => {
// Your sync implementation
return [{ id: "1" }, { id: "2" }];
},
});
Complete Example
Basic Connector
Copy
Ask AI
import { createConnector, createAction, createSync } from "@databite/build";
import { createFlow } from "@databite/flow";
import { z } from "zod";
// Define configuration schemas
const integrationConfig = z.object({
apiKey: z.string(),
baseUrl: z.string().url(),
});
const connectionConfig = z.object({
userId: z.string(),
accessToken: z.string(),
});
// Create authentication flow
const authFlow = createFlow("authenticate").httpBlock("validate", {
url: (input) => `${input.baseUrl}/auth/validate`,
method: "POST",
headers: { Authorization: `Bearer ${input.apiKey}` },
});
// Create the connector
const myConnector = createConnector()
.withIdentity("my-service", "My Service")
.withVersion("1.0.0")
.withAuthor("Your Name")
.withLogo("https://example.com/logo.png")
.withDescription("Connector for My Service API")
.withIntegrationConfig(integrationConfig)
.withConnectionConfig(connectionConfig)
.withAuthenticationFlow(authFlow)
.withActions({
getUser: createAction({
label: "Get User",
description: "Fetch user information",
inputSchema: z.object({ id: z.string() }),
outputSchema: z.object({ user: z.any() }),
handler: async (params, connection) => {
const response = await fetch(
`${connection.config.baseUrl}/users/${params.id}`,
{
headers: {
Authorization: `Bearer ${connection.config.accessToken}`,
},
}
);
return { user: await response.json() };
},
}),
})
.withSyncs({
syncUsers: createSync({
label: "Sync Users",
description: "Synchronize all users",
schedule: "0 2 * * *", // Daily at 2 AM
outputSchema: z.array(z.any()),
handler: async (connection) => {
const response = await fetch(`${connection.config.baseUrl}/users`, {
headers: { Authorization: `Bearer ${connection.config.accessToken}` },
});
return await response.json();
},
}),
})
.withTags("api", "users", "saas")
.build();
Advanced Connector with Error Handling
Copy
Ask AI
import { createConnector, createAction } from "@databite/build";
import { z } from "zod";
const advancedConnector = createConnector()
.withIdentity("advanced-service", "Advanced Service")
.withVersion("2.0.0")
.withAuthor("Advanced Team")
.withLogo("https://example.com/advanced-logo.png")
.withDescription("Advanced connector with comprehensive error handling")
.withIntegrationConfig(
z.object({
apiKey: z.string(),
retryAttempts: z.number().default(3),
timeout: z.number().default(30000),
})
)
.withConnectionConfig(
z.object({
accessToken: z.string(),
refreshToken: z.string().optional(),
})
)
.withActions({
complexOperation: createAction({
label: "Complex Operation",
description: "Perform a complex operation with error handling",
inputSchema: z.object({
data: z.any(),
options: z
.object({
validate: z.boolean().default(true),
timeout: z.number().default(30000),
})
.optional(),
}),
outputSchema: z.object({
result: z.any(),
metadata: z.object({
processedAt: z.string(),
duration: z.number(),
}),
}),
maxRetries: 5,
timeout: 60000,
handler: async (params, connection) => {
const startTime = Date.now();
try {
// Validate input if requested
if (params.options?.validate) {
// Add validation logic here
}
// Perform the operation
const result = await performComplexOperation(params.data, connection);
return {
result,
metadata: {
processedAt: new Date().toISOString(),
duration: Date.now() - startTime,
},
};
} catch (error) {
console.error("Complex operation failed:", error);
throw error;
}
},
}),
})
.build();
async function performComplexOperation(data: any, connection: any) {
// Your complex operation implementation
return { processed: data };
}
Configuration
Integration Configuration
Define the schema for integration-level configuration:Copy
Ask AI
const integrationConfig = z.object({
apiKey: z.string().min(1, "API key is required"),
baseUrl: z.string().url("Must be a valid URL"),
timeout: z.number().min(1000).max(60000).default(30000),
retryAttempts: z.number().min(0).max(10).default(3),
});
Connection Configuration
Define the schema for connection-level configuration:Copy
Ask AI
const connectionConfig = z.object({
accessToken: z.string(),
refreshToken: z.string().optional(),
userId: z.string(),
permissions: z.array(z.string()).optional(),
});
Best Practices
1. Use Descriptive Names
Copy
Ask AI
// Good
.withIdentity("slack-api", "Slack API Integration")
// Avoid
.withIdentity("slack", "Slack")
2. Provide Clear Descriptions
Copy
Ask AI
// Good
.withDescription("Connect to Slack workspace to send messages, manage channels, and sync user data")
// Avoid
.withDescription("Slack connector")
3. Use Proper Error Handling
Copy
Ask AI
const action = createAction({
// ... other config
handler: async (params, connection) => {
try {
const result = await apiCall(params);
return result;
} catch (error) {
if (error.status === 401) {
throw new Error(
"Authentication failed. Please check your credentials."
);
}
if (error.status === 429) {
throw new Error("Rate limit exceeded. Please try again later.");
}
throw new Error(`API call failed: ${error.message}`);
}
},
});
4. Use Appropriate Timeouts
Copy
Ask AI
// For quick operations
const quickAction = createAction({
timeout: 10000, // 10 seconds
// ...
});
// For data-intensive operations
const dataSync = createSync({
timeout: 300000, // 5 minutes
// ...
});
Testing
Unit Testing Actions
Copy
Ask AI
import { createAction } from "@databite/build";
const testAction = createAction({
label: "Test Action",
description: "Test action for unit testing",
inputSchema: z.object({ input: z.string() }),
outputSchema: z.object({ output: z.string() }),
handler: async (params) => {
return { output: `processed: ${params.input}` };
},
});
// Test the action
const result = await testAction.handler({ input: "test" }, mockConnection);
expect(result).toEqual({ output: "processed: test" });
TypeScript Support
The package provides full TypeScript support with automatic type inference:Copy
Ask AI
// Types are automatically inferred from schemas
const connector = createConnector()
.withIntegrationConfig(
z.object({
apiKey: z.string(),
baseUrl: z.string(),
})
)
.withConnectionConfig(
z.object({
accessToken: z.string(),
})
)
.build();
// TypeScript knows the exact shape of integration and connection configs
type IntegrationConfig = z.infer<typeof connector.integrationConfig>;
type ConnectionConfig = z.infer<typeof connector.connectionConfig>;
Related Packages
- @databite/flow - Flow engine for complex workflows
- @databite/types - Shared TypeScript types
- @databite/connectors - Pre-built connector library
- @databite/engine - Data synchronization and execution engine