@t1mmen/srtd
Version:
Supabase Repeatable Template Definitions (srtd): 🪄 Live-reloading SQL templates for Supabase DX. Make your database changes reviewable and migrations maintainable! 🚀
209 lines (208 loc) • 7.06 kB
TypeScript
/**
* Orchestrator Service - Central coordinator for unidirectional data flow
* Manages coordination between FileSystemService, StateService, DatabaseService, and MigrationBuilder
* Implements the flow: FileSystem Event → Orchestrator → StateService (check) → Action → StateService (update)
*/
import EventEmitter from 'node:events';
import type { CLIConfig, ProcessedTemplateResult, TemplateStatus } from '../types.js';
import type { ValidationWarning } from '../utils/schemas.js';
/**
* Event types for Orchestrator - defines the payload for each event.
* Used for type-safe event emission and subscription.
*/
export interface OrchestratorEvents {
templateChanged: TemplateStatus;
templateApplied: TemplateStatus;
templateError: {
template: TemplateStatus;
error: string;
hint?: string;
};
operationComplete: ProcessedTemplateResult;
}
export interface ApplyOptions {
force?: boolean;
templatePaths?: string[];
silent?: boolean;
/** Sort templates by dependencies before processing (default: true) */
respectDependencies?: boolean;
}
export interface BuildOptions {
force?: boolean;
bundle?: boolean;
templatePaths?: string[];
silent?: boolean;
/** Sort templates by dependencies before processing (default: true) */
respectDependencies?: boolean;
}
export interface WatchOptions {
silent?: boolean;
initialProcess?: boolean;
}
export interface OrchestratorConfig {
baseDir: string;
cliConfig: CLIConfig;
silent?: boolean;
}
export declare class Orchestrator extends EventEmitter implements Disposable {
private fileSystemService;
private stateService;
private databaseService;
private migrationBuilder;
private config;
private configWarnings;
private processQueue;
private pendingRecheck;
private processingTemplate;
private processing;
private watching;
constructor(config: OrchestratorConfig, configWarnings?: ValidationWarning[]);
emit<K extends keyof OrchestratorEvents>(event: K, payload: OrchestratorEvents[K]): boolean;
on<K extends keyof OrchestratorEvents>(event: K, listener: (payload: OrchestratorEvents[K]) => void): this;
once<K extends keyof OrchestratorEvents>(event: K, listener: (payload: OrchestratorEvents[K]) => void): this;
off<K extends keyof OrchestratorEvents>(event: K, listener: (payload: OrchestratorEvents[K]) => void): this;
/**
* Initialize the orchestrator and all services
*/
initialize(): Promise<void>;
/**
* Initialize all coordinated services
*/
private initializeServices;
/**
* Set up event listeners for service coordination
*/
private setupEventListeners;
/**
* Handle FileSystem events - Entry point for unidirectional flow
* Uses queue + pendingRecheck to prevent race conditions from rapid file changes
*/
private handleFileSystemEvent;
/**
* Process the next template in the queue
*/
private processNextTemplate;
/**
* Process a single template through the unidirectional flow
*/
private processTemplate;
/**
* Get template status by coordinating between services.
* Accepts optional cached template file to avoid redundant disk reads.
*/
private getTemplateStatus;
/**
* Execute apply operation for a template.
* Accepts optional cached template file to avoid redundant disk reads.
*/
private executeApplyTemplate;
/**
* Command handler: Apply templates to database
*/
apply(options?: ApplyOptions): Promise<ProcessedTemplateResult>;
/**
* Command handler: Build migration files from templates
*/
build(options?: BuildOptions): Promise<ProcessedTemplateResult>;
/**
* Execute bundled migration build
*/
private executeBundledBuild;
/**
* Execute individual migration builds
*/
private executeIndividualBuilds;
/**
* Build a single template migration file
*/
private executeBuildTemplate;
/**
* Command handler: Start watching for template changes
*/
watch(options?: WatchOptions): Promise<{
close: () => Promise<void>;
}>;
/**
* Find all templates using FileSystemService
*/
findTemplates(): Promise<string[]>;
/**
* Get template status for external consumers
*/
getTemplateStatusExternal(templatePath: string): Promise<TemplateStatus>;
/**
* Register a template in the build log without building it
* Used when importing existing migrations that should be tracked
*/
registerTemplate(templatePath: string): Promise<void>;
/**
* Promote a WIP template by renaming it and updating build logs
* @returns The new path after promotion
*/
promoteTemplate(templatePath: string): Promise<string>;
/**
* Clear build logs via StateService (single source of truth)
* @param type - 'local' clears local only, 'shared' clears shared only, 'both' clears all
*/
clearBuildLogs(type: 'local' | 'shared' | 'both'): Promise<void>;
/**
* Get all validation warnings (config + build logs)
* Returns combined warnings from config loading and build log loading
*/
getValidationWarnings(): ValidationWarning[];
/**
* Get recently applied templates (for history display)
*/
getRecentlyApplied(limit?: number): Array<{
template: string;
appliedDate: string;
}>;
/**
* Get template info including migration file and last date
* Used for displaying arrow format: template.sql → migration_file.sql
*/
getTemplateInfo(templatePath: string): {
template: string;
migrationFile?: string;
lastDate?: string;
};
/**
* Get recent activity for watch mode history display.
* Returns the most recent builds and applies sorted by date.
*/
getRecentActivity(limit?: number): Array<{
template: string;
action: 'built' | 'applied';
timestamp: Date;
target?: string;
}>;
/**
* Sort templates by their SQL dependencies
* Reads all templates, builds a dependency graph, and returns topologically sorted paths
*/
private sortByDependencies;
/**
* Logging utility
*/
private log;
/**
* Dispose of all services and clean up (async version for proper cleanup)
*/
dispose(): Promise<void>;
/**
* Async dispose for await using statement - ensures cleanup completes
*/
[Symbol.asyncDispose](): Promise<void>;
/**
* Synchronous dispose for using statement - schedules async cleanup
* Note: For proper cleanup, prefer await using with Symbol.asyncDispose
*/
[Symbol.dispose](): void;
/**
* Create orchestrator from CLI configuration
*/
static create(baseDir: string, cliConfig: CLIConfig, options?: {
silent?: boolean;
configWarnings?: ValidationWarning[];
}): Promise<Orchestrator>;
}