@seedts/core
v0.1.1
Published
Core execution engine for SeedTS
Downloads
10
Maintainers
Readme
@seedts/core
Core execution engine for SeedTS
The core package provides the execution engine, seed registry, dependency resolution, and transaction management for SeedTS. It's the heart of the SeedTS ecosystem.
Installation
pnpm add @seedts/core @seedts/typesNote: This package is automatically included when you install the main
seedtspackage.
Features
- Executor - Executes seeds in the correct order with dependency resolution
- Seed Registry - Manages and organizes seeds
- Dependency Graph - Automatic topological sorting of seed dependencies
- Transaction Manager - Wraps seed execution in database transactions
- Parallel Execution - Run independent seeds concurrently
- Rollback Support - Automatic rollback on failure
Quick Start
Creating a Seed
import { seed } from '@seedts/core';
import type { User } from './types';
const userSeed = seed<User>('users')
.adapter(myAdapter)
.data([
{ email: '[email protected]', name: 'Admin', role: 'admin' },
{ email: '[email protected]', name: 'User', role: 'user' },
])
.build();Using Factory Functions
const userSeed = seed<User>('users')
.adapter(myAdapter)
.factory(async (ctx) => {
return Array.from({ length: 100 }, (_, i) => ({
email: `user${i}@example.com`,
name: `User ${i}`,
role: 'user',
}));
})
.build();Executing Seeds
import { Executor } from '@seedts/core';
const executor = new Executor([userSeed, postSeed, commentSeed]);
const results = await executor.execute({
parallel: false, // Run seeds sequentially
transaction: true, // Wrap in transaction
verbose: true, // Log progress
});
console.log(results);
// [
// { name: 'users', inserted: 100, duration: 45, ... },
// { name: 'posts', inserted: 500, duration: 120, ... },
// { name: 'comments', inserted: 2000, duration: 350, ... }
// ]Core API
seed<T>(name: string)
Creates a new seed builder with a fluent API:
import { seed } from '@seedts/core';
const mySeed = seed<MyType>('table-name')
.adapter(adapter)
.data([...]) // Static data
.factory(factoryFn) // Dynamic data generation
.dependsOn(['other']) // Dependencies
.onConflict('skip') // Conflict strategy
.hooks({...}) // Lifecycle hooks
.build();Executor
Manages and executes multiple seeds:
import { Executor } from '@seedts/core';
const executor = new Executor(seeds, {
parallel: true, // Enable parallel execution
maxParallel: 5, // Max concurrent seeds
transaction: true, // Use transactions
verbose: false, // Logging
continueOnError: false, // Stop on first error
});
// Execute all seeds
const results = await executor.execute();
// Execute specific seeds
const results = await executor.execute({
only: ['users', 'posts'],
});
// Dry run (validate without executing)
const validation = await executor.validate();SeedRegistry
Manages seed registration and lookup:
import { SeedRegistry } from '@seedts/core';
const registry = new SeedRegistry();
// Register seeds
registry.register(userSeed);
registry.register(postSeed);
// Get seed by name
const seed = registry.get('users');
// Get all seeds
const allSeeds = registry.getAll();
// Check if seed exists
const exists = registry.has('users');DependencyGraph
Resolves seed dependencies and performs topological sorting:
import { DependencyGraph } from '@seedts/core';
const graph = new DependencyGraph(seeds);
// Get execution order
const order = graph.getExecutionOrder();
// ['users', 'posts', 'comments']
// Detect circular dependencies
const cycles = graph.detectCycles();
// Get independent seeds that can run in parallel
const batches = graph.getParallelBatches();
// [
// ['users', 'categories'], // Batch 1: no dependencies
// ['posts', 'tags'], // Batch 2: depend on batch 1
// ['comments'] // Batch 3: depends on posts
// ]Seed Configuration
Dependencies
const postSeed = seed<Post>('posts')
.dependsOn('users') // Single dependency
.adapter(adapter)
.factory(async (ctx) => {
const users = await ctx.getSeed('users');
return posts.map(p => ({ ...p, userId: users[0].id }));
})
.build();
const commentSeed = seed<Comment>('comments')
.dependsOn(['users', 'posts']) // Multiple dependencies
.adapter(adapter)
.factory(async () => comments)
.build();Conflict Strategies
const seed = seed<User>('users')
.adapter(adapter)
.data(users)
.onConflict('skip') // Skip existing records
// .onConflict('update') // Update existing records
// .onConflict('error') // Throw error on conflict
.build();Lifecycle Hooks
const seed = seed<User>('users')
.adapter(adapter)
.hooks({
beforeInsert: async (data) => {
console.log(`Inserting ${data.length} users`);
return data.map(u => ({ ...u, createdAt: new Date() }));
},
afterInsert: async (data, inserted) => {
console.log(`Inserted ${inserted.length} users`);
},
onSuccess: async (data, metadata) => {
console.log(`Success! Duration: ${metadata.duration}ms`);
},
onError: async (error) => {
console.error('Seeding failed:', error);
},
})
.build();Execution Context
The execution context provides useful information and utilities:
const factory = async (ctx) => {
// Current index and total count
console.log(`${ctx.index + 1} of ${ctx.count}`);
// Seed name
console.log(ctx.seedName);
// Get data from other seeds
const users = await ctx.getSeed('users');
// Get inserted data from specific seed
const insertedUsers = ctx.getInsertedData('users');
// Custom metadata
ctx.metadata.customData = 'value';
return generatedData;
};Transaction Management
import { TransactionManager } from '@seedts/core';
const txManager = new TransactionManager(adapter);
await txManager.run(async () => {
// All operations here are in a transaction
await adapter.insert('users', users);
await adapter.insert('posts', posts);
// Automatically commits if no error
// Automatically rolls back on error
});Error Handling
import {
SeedExecutionError,
SeedDependencyError,
SeedValidationError,
} from '@seedts/core';
try {
await executor.execute();
} catch (error) {
if (error instanceof SeedDependencyError) {
console.error('Dependency error:', error.message);
console.error('Missing:', error.missing);
console.error('Circular:', error.circular);
} else if (error instanceof SeedExecutionError) {
console.error('Execution failed:', error.seedName);
console.error('Original error:', error.cause);
} else if (error instanceof SeedValidationError) {
console.error('Validation failed:', error.errors);
}
}Advanced Usage
Custom Seed Implementation
import { BaseSeed } from '@seedts/core';
import type { SeedDefinition } from '@seedts/types';
class CustomSeed extends BaseSeed {
async execute(context) {
// Custom execution logic
const data = await this.generateData(context);
const inserted = await this.adapter.insert(this.name, data);
return { inserted, metadata: {} };
}
}Extending the Executor
import { Executor } from '@seedts/core';
class CustomExecutor extends Executor {
async beforeExecution() {
// Custom pre-execution logic
console.log('Starting seed execution...');
}
async afterExecution(results) {
// Custom post-execution logic
console.log(`Completed ${results.length} seeds`);
}
}API Reference
For detailed API documentation, visit:
Related Packages
- @seedts/types - Core type definitions
- @seedts/adapters - Base adapter classes
- @seedts/cli - Command-line interface
- seedts - Main convenience package
Contributing
Contributions are welcome! Please see our Contributing Guide.
License
MIT © SeedTS Contributors
