Processor Development
Create custom file transformers for CyanPrint templates
Processor Development
Processors are the transformation engines that convert template files into generated output. The default processor uses Eta templating, but you can create custom processors for any transformation needs.
What is a Processor?
A processor is a Docker container that:
- Receives files from the template's blob image
- Transforms content based on configuration
- Outputs files to the write directory
Processors are stateless file transformers - they receive input files and produce output files without side effects.
Processor Architecture
Components
| Component | Purpose | Examples |
|---|---|---|
| Entry Point | Processor logic | StartProcessorWithLambda |
| CyanFileHelper | File operations | resolveAll(), read(), copy() |
| CyanProcessorInput | Input from template | Config, globs, directories |
| ProcessorOutput | Return value | Output directory path |
Why Create a Custom Processor?
Different Templating Engines
The default processor uses Eta with var__name__ syntax. You might need:
| Engine | Use Case |
|---|---|
| Jinja | Python-style templates |
| Go templates | Helm/Kubernetes manifests |
| Mustache | Logic-less templates |
| Handlebars | Rich template features |
Custom Logic
Processors enable custom processing that goes beyond simple variable substitution:
- Code generation (GraphQL, Protobuf, OpenAPI)
- AST transformations
- Binary file processing
- Multi-step pipelines
Processors should be pure functions - same input always produces same output. This ensures reproducible project generation.
Learning Path
Tutorials
Build your first processor step by step
How-To Guides
Task-oriented guides for common scenarios
Reference
Technical documentation for the SDK
Explanation
Deep dives into processor concepts
Quick Example
Here's a minimal processor that uppercases all file content:
import { StartProcessorWithLambda } from '@atomicloud/cyan-sdk';StartProcessorWithLambda(async (input, fileHelper) => {const files = fileHelper.resolveAll();files.forEach(file => {file.content = file.content.toUpperCase();file.writeFile();});return { directory: input.writeDir };});
from cyanprintsdk.processor import start_processor_with_fnfrom cyanprintsdk.protocol import ProcessorInput, ProcessorOutputasync def processor(input: ProcessorInput, file_helper) -> ProcessorOutput:files = file_helper.resolve_all()for file in files:file.content = file.content.upper()file.write_file()return ProcessorOutput(directory=input.write_dir)processor_main = start_processor_with_fn(processor)
using CyanPrintSDK;public static class Processor{[ProcessorMain]public static async Task<ProcessorOutput> Run(ProcessorInput input, CyanFileHelper fileHelper){var files = fileHelper.ResolveAll();foreach (var file in files){file.Content = file.Content.ToUpper();file.WriteFile();}return new ProcessorOutput { Directory = input.WriteDir };}}