Core Package - Shared Library Documentation
Note: This package is a shared dependency used by all other n8n-as-code packages. It provides the foundational services for workflow management.
๐ฏ Purposeโ
The Core package (@n8n-as-code/core) provides the shared business logic and services used by:
- VS Code Extension: For workflow synchronization and management
- CLI: For command-line operations
- Agent CLI: For AI context generation
It encapsulates all n8n API interactions, state management, and synchronization logic.
๐๏ธ Architectureโ
3-Way Merge Architectureโ
The Core package implements a 3-way merge architecture that separates concerns cleanly:
graph TD
A[SyncManager] --> B[Watcher]
A --> C[SyncEngine]
A --> D[ResolutionManager]
B --> E[StateManager]
C --> E
C --> F[N8nApiClient]
C --> G[WorkflowSanitizer]
C --> H[DirectoryUtils]
E --> I[.n8n-state.json]
F --> J[n8n API]
G --> K[Validation]
H --> L[File System]
style A fill:#ff6b35
style B fill:#3498db
style C fill:#2ecc71
style D fill:#9b59b6
Key Design Principles:
- Watcher observes state (file system + API) and emits status events
- SyncEngine mutates state (performs I/O operations)
- ResolutionManager handles interactive conflict resolution
- SyncManager orchestrates the components
- StateManager maintains the "base" state for 3-way comparison
Package Dependenciesโ
{
"dependencies": {
"axios": "^1.6.0", // HTTP client for n8n API
"fs-extra": "^11.1.1", // Enhanced file system operations
"json-schema": "^0.4.0", // JSON Schema validation
"chokidar": "^3.5.3" // File watching
}
}
๐งฉ Core Servicesโ
1. Watcher (src/services/watcher.ts)โ
Passive observer service that detects changes without performing synchronization.
Key Responsibilities:
- Watch file system for local changes using
chokidar(debounced 500ms) - Poll n8n API for remote changes (configurable interval)
- Calculate workflow status using 3-way comparison
- Emit status events for SyncManager to handle
- Never perform any synchronization operations (read-only)
Events Emitted:
watcher.on('status-changed', (status: IWorkflowStatus) => {...});
watcher.on('conflict', (conflict: IWorkflowStatus) => {...});
watcher.on('deletion', (deletion: IWorkflowStatus) => {...});
Status Detection Algorithm: Uses 3-way merge comparison (base vs local vs remote):
// Pseudo-code for status detection
if (!existsLocally && !existsRemotely) return null;
if (!existsLocally) return DELETED_LOCALLY;
if (!existsRemotely && !lastSynced) return EXIST_ONLY_LOCALLY;
if (!existsRemotely && lastSynced) return DELETED_REMOTELY;
if (!lastSynced) return EXIST_ONLY_REMOTELY;
if (localHash === remoteHash) return IN_SYNC;
if (localHash === lastSyncedHash) return MODIFIED_REMOTELY;
if (remoteHash === lastSyncedHash) return MODIFIED_LOCALLY;
return CONFLICT; // Both changed since last sync
2. SyncEngine (src/services/sync-engine.ts)โ
Stateless I/O executor that performs actual synchronization operations.
Key Responsibilities:
- Execute push operations (local โ remote)
- Execute pull operations (remote โ local)
- Delete workflows from local or remote
- Finalize sync by updating
.n8n-state.json - Create backups before destructive operations
- Never decide what to sync (receives instructions from SyncManager)
Core Methods:
class SyncEngine {
async push(workflow: IWorkflowStatus): Promise<void>;
async pull(workflow: IWorkflowStatus): Promise<void>;
async delete(workflow: IWorkflowStatus, target: 'local' | 'remote'): Promise<void>;
async finalizeSync(workflowId: string, filename: string): Promise<void>;
}
Atomic Operations:
- Uses temporary files for safe writes
- Creates timestamped backups in
.trash/directory - Updates state only after successful API/file operations
3. ResolutionManager (src/services/resolution-manager.ts)โ
Handles interactive conflict and deletion resolution.
Key Responsibilities:
- Prompt user for conflict resolution choices
- Prompt user for deletion confirmation
- Display diffs between local and remote versions
- Keep resolution logic separate from sync logic
Resolution Flow:
class ResolutionManager {
async promptForConflict(workflow: IWorkflowStatus): Promise<'local' | 'remote' | 'skip'>;
async promptForDeletion(workflow: IWorkflowStatus): Promise<'delete' | 'restore' | 'skip'>;
async showDiff(workflow: IWorkflowStatus): Promise<void>;
}
4. SyncManager (src/services/sync-manager.ts)โ
High-level orchestrator that coordinates all components.
Key Responsibilities:
- Orchestrate Watcher, SyncEngine, and ResolutionManager
- Implement high-level sync strategies (syncUp, syncDown, startWatching)
- Handle event forwarding and aggregation
- Provide public API for CLI and VS Code extension
Public API:
class SyncManager extends EventEmitter {
async refreshState(): Promise<void>;
async syncUp(): Promise<void>;
async syncDown(): Promise<void>;
async startWatching(): Promise<void>;
async stopWatching(): Promise<void>;
async getWorkflowsStatus(): Promise<IWorkflowStatus[]>;
async resolveConflict(id: string, filename: string, choice: 'local' | 'remote'): Promise<void>;
}
Events Emitted:
syncManager.on('log', (message: string) => {...});
syncManager.on('conflict', (conflict: IWorkflowStatus) => {...});
syncManager.on('deletion', (deletion: IWorkflowStatus) => {...});
syncManager.on('statusChanged', (status: IWorkflowStatus) => {...});
5. StateManager (src/services/state-manager.ts)โ
Manages .n8n-state.json file that tracks the "base" state for 3-way merge.
Key Responsibilities:
- Load and save
.n8n-state.json - Track
lastSyncedHashandlastSyncedAtfor each workflow - Provide the "base" state for 3-way comparison
- Enable deterministic conflict detection
State File Structure:
interface IInstanceState {
workflows: {
[workflowId: string]: IWorkflowState;
};
}
interface IWorkflowState {
lastSyncedHash: string; // SHA-256 hash of last synced content
lastSyncedAt: string; // ISO timestamp
}
Core Methods:
class StateManager {
async loadState(): Promise<IInstanceState>;
async saveState(state: IInstanceState): Promise<void>;
async updateWorkflowState(workflowId: string, hash: string): Promise<void>;
getWorkflowState(workflowId: string): IWorkflowState | undefined;
}
6. N8nApiClient (src/services/n8n-api-client.ts)โ
Communicates with the n8n REST API.
Key Responsibilities:
- Handle authentication and API key management
- Make HTTP requests to n8n endpoints
- Handle rate limiting and retries
- Parse and validate API responses
API Endpoints:
interface N8nApiClient {
// Workflow operations
getWorkflows(): Promise<Workflow[]>;
getWorkflow(id: string): Promise<Workflow>;
createWorkflow(workflow: Workflow): Promise<Workflow>;
updateWorkflow(id: string, workflow: Workflow): Promise<Workflow>;
deleteWorkflow(id: string): Promise<void>;
// Instance operations
getInstances(): Promise<Instance[]>;
getInstance(id: string): Promise<Instance>;
// Health check
healthCheck(): Promise<HealthStatus>;
}
7. WorkflowSanitizer (src/services/workflow-sanitizer.ts)โ
Validates and sanitizes workflow JSON.
Key Responsibilities:
- Validate workflow structure against n8n schema
- Remove sensitive data (credentials, API keys)
- Normalize workflow format
- Fix common issues and inconsistencies
Sanitization Process:
interface WorkflowSanitizer {
sanitize(workflow: any): SanitizedWorkflow;
validate(workflow: any): ValidationResult;
normalize(workflow: any): NormalizedWorkflow;
removeCredentials(workflow: any): CredentialFreeWorkflow;
}
8. DirectoryUtils (src/services/directory-utils.ts)โ
Manages file system operations for workflows.
Key Responsibilities:
- Create and manage workflow directory structure
- Handle file I/O operations
- Organize workflows by instance
- Provide path utilities
Directory Structure:
workflows/
โโโ instance1/
โ โโโ workflow-a.json
โ โโโ workflow-b.json
โโโ instance2/
โ โโโ workflow-c.json
โโโ .state.json
6. TrashServiceโ
Manages deleted workflows and provides recovery.
Key Responsibilities:
- Move deleted workflows to trash
- Provide trash management operations
- Support workflow recovery
- Automatic trash cleanup
๐ Sync Processโ
Full Sync Flowโ
sequenceDiagram
participant User
participant SyncManager
participant StateManager
participant N8nApiClient
participant DirectoryUtils
User->>SyncManager: sync()
SyncManager->>StateManager: getState()
StateManager-->>SyncManager: current state
SyncManager->>N8nApiClient: getWorkflows()
N8nApiClient-->>SyncManager: remote workflows
SyncManager->>DirectoryUtils: readLocalWorkflows()
DirectoryUtils-->>SyncManager: local workflows
SyncManager->>StateManager: compareStates()
StateManager-->>SyncManager: changes detected
loop For each change
SyncManager->>SyncManager: applyChange()
end
SyncManager->>StateManager: updateState()
SyncManager-->>User: sync completed
Conflict Resolutionโ
- Detection: StateManager detects hash mismatch
- Analysis: Determine conflict type (edit/edit, delete/edit, etc.)
- Notification: Report conflict to user
- Resolution: Apply resolution strategy
- Sync: Continue with resolved workflow
๐ State Managementโ
State File Structureโ
{
"version": "1.0.0",
"workflows": {
"workflow-id-1": {
"id": "workflow-id-1",
"name": "My Workflow",
"localPath": "workflows/instance1/my-workflow.json",
"remoteId": "123",
"localHash": "abc123",
"remoteHash": "def456",
"lastSync": "2024-01-13T09:41:02.177Z",
"status": "synced"
}
},
"instances": {
"instance1": {
"host": "https://n8n.example.com",
"lastSync": "2024-01-13T09:41:02.177Z"
}
}
}
State Operationsโ
- Read State: Load from
.state.json - Update State: Modify and save state
- Merge States: Combine multiple state sources
- Validate State: Ensure state consistency
๐ Securityโ
Credential Handlingโ
- Never Store: Credentials are never stored in state or files
- API Key Encryption: API keys encrypted in memory
- Secure Transmission: HTTPS for all API calls
- Input Validation: Validate all inputs before processing
Data Sanitizationโ
- Workflow Sanitization: Remove credentials before storage
- Error Messages: Sanitize error messages to avoid information leakage
- Logging: No sensitive data in logs
๐งช Testingโ
Test Structureโ
packages/core/tests/
โโโ unit/
โ โโโ state-manager.test.ts
โ โโโ workflow-sanitizer.test.ts
โโโ integration/
โโโ sync-scenarios.test.ts
Test Coverageโ
- Unit Tests: Individual service testing
- Integration Tests: Service interaction testing
- Mocking: Nock for HTTP, mock-fs for file system
- Snapshot Tests: State persistence testing
Running Testsโ
cd packages/core
npm test
๐ Performanceโ
Optimization Strategiesโ
- Batch Operations: Process multiple workflows in batches
- Caching: Cache API responses and file reads
- Incremental Sync: Only sync changed workflows
- Parallel Processing: Concurrent operations where safe
Memory Managementโ
- Stream Processing: Process large workflows as streams
- Cleanup: Proper disposal of resources
- Monitoring: Track memory usage and leaks
๐ง Configurationโ
Configuration Interfaceโ
interface CoreConfig {
host: string;
apiKey: string;
syncFolder: string;
syncMode: 'auto' | 'manual';
pollInterval: number;
maxRetries: number;
timeout: number;
ignorePatterns: string[];
}
Configuration Sourcesโ
- File:
n8n-as-code.json - Environment Variables:
N8N_HOST,N8N_API_KEY, etc. - Command Line: CLI arguments
- Defaults: Built-in default values
๐ Developmentโ
Buildingโ
cd packages/core
npm run build
Development Modeโ
cd packages/core
npm run dev
TypeScript Configurationโ
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"declarationMap": true
}
}
๐ Related Documentationโ
- Architecture Overview: Overall system architecture
- Agent CLI: AI integration details
- Contribution Guide: How to contribute
The Core package provides the foundation for all n8n-as-code functionality, ensuring consistent behavior across different interfaces while maintaining security and performance.