ProcessorsHow-To Guides
Access Processor Config
Access configuration passed from template
Access Processor Config
Processors receive configuration from the template through input.config. This allows templates to customize processor behavior.
ProcessorConfig Type
Prop
Type
Template Configuration
In the template's index.ts, pass config to the processor:
index.ts
// Template's index.tsimport { StartTemplateWithLambda, GlobType } from '@atomicloud/cyan-sdk';interface ProcessorConfig {customSetting: boolean;features: string[];outputFormat: 'json' | 'yaml';}StartTemplateWithLambda(async (i, d) => {// Ask user for preferencesconst features = await i.checkbox('Select features:',['docker', 'ci', 'testing'],'project.features','Choose features');const format = await i.select('Output format:',['json', 'yaml'],'config.format','Choose format');return {processors: [{name: 'myorg/my-processor',files: [{ root: 'templates', glob: '**/*', exclude: [], type: GlobType.Template }],config: {customSetting: true,features: features,outputFormat: format} as ProcessorConfig}]};});
Accessing Config in Processor
index.ts
// Processor's index.tsimport { StartProcessorWithLambda } from '@atomicloud/cyan-sdk';interface ProcessorConfig {customSetting: boolean;features: string[];outputFormat: 'json' | 'yaml';}StartProcessorWithLambda(async (input, fileHelper) => {// Cast config to your typeconst config = input.config as ProcessorConfig;// Use config valuesif (config.customSetting) {console.log('Custom setting enabled');}const files = fileHelper.resolveAll();files.forEach(file => {if (config.features.includes('docker')) {// Modify file.content as needed for docker feature}if (config.outputFormat === 'yaml') {// Convert file.content to YAML format}file.writeFile();});return { directory: input.writeDir };});
index.py
from cyanprintsdk import start_processor_with_fnfrom cyanprintsdk.domain.processor.input import ProcessorInputfrom cyanprintsdk.domain.core.fs.cyan_fs_helper import CyanFileHelperfrom typing import TypedDict, List, Literalclass ProcessorConfig(TypedDict):customSetting: boolfeatures: List[str]outputFormat: Literal['json', 'yaml']async def my_processor(input: ProcessorInput, fileHelper: CyanFileHelper):# Cast config to your typeconfig: ProcessorConfig = input.config# Use config valuesif config.get('customSetting'):print('Custom setting enabled')files = fileHelper.resolve_all()for file in files:if 'docker' in config.get('features', []):# Modify file.content as needed for docker featurepassif config.get('outputFormat') == 'yaml':# Convert file.content to YAML formatpassfile.write_file()return {'directory': input.write_directory}start_processor_with_fn(my_processor)
Program.cs
using sulfone_helium;using sulfone_helium.Domain.Core.FileSystem;using sulfone_helium.Domain.Processor;// Processor config classpublic class ProcessorConfig{public bool CustomSetting { get; set; }public List<string> Features { get; set; } = new();public string OutputFormat { get; set; } = "json";}CyanEngine.StartProcessor(args, async (input, fileHelper) =>{// Cast config to your typevar config = input.Config.Deserialize<ProcessorConfig>();// Use config valuesif (config.CustomSetting){Console.WriteLine("Custom setting enabled");}var files = fileHelper.ResolveAll();foreach (var file in files){if (config.Features.Contains("docker")){// Modify file.Content as needed for docker feature}if (config.OutputFormat == "yaml"){// Convert file.Content to YAML format}file.WriteFile();}return new ProcessorOutput { Directory = input.WriteDirectory };});
Default Config Values
Always handle missing config gracefully:
index.ts
interface ProcessorConfig {includeComments?: boolean;indentSize?: number;generateTypes?: boolean;}StartProcessorWithLambda(async (input, fileHelper) => {// Provide defaults for missing valuesconst config: ProcessorConfig = {includeComments: true,indentSize: 2,generateTypes: false,...(input.config as Partial<ProcessorConfig>)};const files = fileHelper.resolveAll();files.forEach(file => {const indent = ' '.repeat(config.indentSize);if (config.generateTypes) {// Generate types from file.content}if (!config.includeComments) {// Remove comments from file.content}file.writeFile();});return { directory: input.writeDir };});
index.py
from cyanprintsdk import start_processor_with_fnfrom cyanprintsdk.domain.processor.input import ProcessorInputfrom cyanprintsdk.domain.core.fs.cyan_fs_helper import CyanFileHelperfrom typing import TypedDict, Optionalclass ProcessorConfig(TypedDict, total=False):includeComments: boolindentSize: intgenerateTypes: boolasync def my_processor(input: ProcessorInput, fileHelper: CyanFileHelper):# Provide defaults for missing valuesraw_config = input.config or {}config: ProcessorConfig = {'includeComments': raw_config.get('includeComments', True),'indentSize': raw_config.get('indentSize', 2),'generateTypes': raw_config.get('generateTypes', False),}files = fileHelper.resolve_all()for file in files:indent = ' ' * config['indentSize']if config['generateTypes']:# Generate types from file.contentpassif not config['includeComments']:# Remove comments from file.contentpassfile.write_file()return {'directory': input.write_directory}start_processor_with_fn(my_processor)
Program.cs
using sulfone_helium;using sulfone_helium.Domain.Core.FileSystem;using sulfone_helium.Domain.Processor;public class ProcessorConfig{public bool IncludeComments { get; set; } = true;public int IndentSize { get; set; } = 2;public bool GenerateTypes { get; set; } = false;}CyanEngine.StartProcessor(args, async (input, fileHelper) =>{// Provide defaults for missing valuesvar rawConfig = input.Config.Deserialize<ProcessorConfig>() ?? new ProcessorConfig();var config = new ProcessorConfig{IncludeComments = rawConfig.IncludeComments,IndentSize = rawConfig.IndentSize,GenerateTypes = rawConfig.GenerateTypes};var files = fileHelper.ResolveAll();foreach (var file in files){var indent = new string(' ', config.IndentSize);if (config.GenerateTypes){// Generate types from file.Content}if (!config.IncludeComments){// Remove comments from file.Content}file.WriteFile();}return new ProcessorOutput { Directory = input.WriteDirectory };});
Complex Config Example
template-config.ts
// Template config{name: 'myorg/codegen-processor',files: [{ root: 'schemas', glob: '**/*.graphql', exclude: [], type: GlobType.Template }],config: {generateClient: true,generateServer: false,clientOptions: {outputDir: 'src/client',fetcher: 'axios',typesOnly: false},scalars: {DateTime: 'Date',JSON: 'Record<string, unknown>'}}}// Processor handling complex configinterface CodegenConfig {generateClient?: boolean;generateServer?: boolean;clientOptions?: {outputDir: string;fetcher: 'axios' | 'fetch';typesOnly: boolean;};scalars?: Record<string, string>;}StartProcessorWithLambda(async (input, fileHelper) => {const config: CodegenConfig = input.config as CodegenConfig;const files = fileHelper.resolveAll();files.forEach(file => {// Parse schema from file.contentconst schema = parseSchema(file.content);if (config.generateClient) {const clientCode = generateClient(schema, config.clientOptions);// Note: To write additional files, use fileHelper to create new VirtualFile instances// and write them to the appropriate output location within input.writeDir}file.writeFile();});return { directory: input.writeDir };});
template_config.py
# Template configtemplate_config = {'name': 'myorg/codegen-processor','files': [{'root': 'schemas', 'glob': '**/*.graphql', 'exclude': [], 'type': GlobType.Template}],'config': {'generateClient': True,'generateServer': False,'clientOptions': {'outputDir': 'src/client','fetcher': 'axios','typesOnly': False},'scalars': {'DateTime': 'Date','JSON': 'Dict[str, Any]'}}}# Processor handling complex configfrom cyanprintsdk import start_processor_with_fnfrom cyanprintsdk.domain.processor.input import ProcessorInputfrom cyanprintsdk.domain.core.fs.cyan_fs_helper import CyanFileHelperfrom typing import TypedDict, Optional, Dict, Any, Literalclass ClientOptions(TypedDict, total=False):outputDir: strfetcher: Literal['axios', 'fetch']typesOnly: boolclass CodegenConfig(TypedDict, total=False):generateClient: boolgenerateServer: boolclientOptions: ClientOptionsscalars: Dict[str, str]async def my_processor(input: ProcessorInput, fileHelper: CyanFileHelper):config: CodegenConfig = input.configfiles = fileHelper.resolve_all()for file in files:# Parse schema from file.contentschema = parse_schema(file.content)if config.get('generateClient'):client_code = generate_client(schema, config.get('clientOptions'))# Note: To write additional files, use fileHelper to create new VirtualFile instances# and write them to the appropriate output location within input.write_directoryfile.write_file()return {'directory': input.write_directory}start_processor_with_fn(my_processor)
TemplateConfig.cs
// Template configvar templateConfig = new{name = "myorg/codegen-processor",files = new[] { new { root = "schemas", glob = "**/*.graphql", exclude = Array.Empty<string>(), type = GlobType.Template } },config = new{generateClient = true,generateServer = false,clientOptions = new{outputDir = "src/client",fetcher = "axios",typesOnly = false},scalars = new Dictionary<string, string>{["DateTime"] = "Date",["JSON"] = "object"}}};// Processor handling complex configpublic class ClientOptions{public string OutputDir { get; set; } = "";public string Fetcher { get; set; } = "axios";public bool TypesOnly { get; set; }}public class CodegenConfig{public bool GenerateClient { get; set; }public bool GenerateServer { get; set; }public ClientOptions? ClientOptions { get; set; }public Dictionary<string, string>? Scalars { get; set; }}CyanEngine.StartProcessor(args, async (input, fileHelper) =>{var config = input.Config.Deserialize<CodegenConfig>();var files = fileHelper.ResolveAll();foreach (var file in files){// Parse schema from file.Contentvar schema = ParseSchema(file.Content);if (config.GenerateClient){var clientCode = GenerateClient(schema, config.ClientOptions);// Note: To write additional files, use fileHelper to create new VirtualFile instances// and write them to the appropriate output location within input.WriteDirectory}file.WriteFile();}return new ProcessorOutput { Directory = input.WriteDirectory };});
Config is passed as unknown type. Always cast to your expected type and provide default values for optional fields.