ProcessorsHow-To Guides
Lazy Load Files
Get file references without loading content
Lazy Load Files
Use get() to get file references without loading content. Load content only when needed.
When to Use
Best for:
- Conditional processing where you may not need all files
- Checking file paths/extensions before loading
- Reducing initial memory footprint
"Lazy" here means deferred loading by you, the developer. The actual file read uses synchronous I/O. For truly memory-efficient large file handling, use fileHelper.readAsStream() instead.
Usage
processor.ts
import { StartProcessorWithLambda } from '@atomicloud/cyan-sdk';StartProcessorWithLambda(async (input, fileHelper) => {// Get references WITHOUT loading contentconst refs = fileHelper.get({ root: 'templates', glob: '**/*' });for (const ref of refs) {console.log(ref.relative); // Path available immediately// ref.content NOT available - must load explicitly// Only load content when neededif (shouldProcess(ref.relative)) {// readFile() returns a VirtualFile with content propertyconst file = ref.readFile();const transformed = processContent(file.content);// Update content and writefile.content = transformed;file.writeFile();} else {// Copy without loading - use fileHelper.copy()fileHelper.copy({ root: 'templates', glob: ref.relative });}}return { directory: input.writeDir };});
processor.py
from cyanprintsdk import start_processor_with_fnfrom cyanprintsdk.domain.processor.input import ProcessorInputfrom cyanprintsdk.domain.core.fs.cyan_fs_helper import CyanFileHelperasync def my_processor(input: ProcessorInput, fileHelper: CyanFileHelper):# Get references WITHOUT loading contentrefs = fileHelper.get(root='templates', glob='**/*')for ref in refs:print(ref.relative) # Path available immediately# ref.content NOT available - must load explicitly# Only load content when neededif should_process(ref.relative):# read_file() returns a VirtualFile with content propertyfile = ref.read_file()transformed = process_content(file.content)# Update content and writefile.content = transformedfile.write_file()else:# Copy without loading - use fileHelper.copy()fileHelper.copy(root='templates', glob=ref.relative)return {'directory': input.write_directory}start_processor_with_fn(my_processor)
Processor.cs
using sulfone_helium;using sulfone_helium.Domain.Core.FileSystem;using sulfone_helium.Domain.Processor;CyanEngine.StartProcessor(args, async (input, fileHelper) =>{// Get references WITHOUT loading contentvar refs = fileHelper.Get(root: "templates", glob: "**/*");foreach (var ref_ in refs){Console.WriteLine(ref_.Relative); // Path available immediately// ref_.Content NOT available - must load explicitly// Only load content when neededif (ShouldProcess(ref_.Relative)){// ReadFile() returns a VirtualFile with Content propertyvar file = ref_.ReadFile();var transformed = ProcessContent(file.Content);// Update content and writefile.Content = transformed;file.WriteFile();}else{// Copy without loading - use fileHelper.Copy()fileHelper.Copy(root: "templates", glob: ref_.Relative);}}return new ProcessorOutput { Directory = input.WriteDirectory };});
VirtualFileReference Properties
Prop
Type
VirtualFileReference Methods
Prop
Type
VirtualFile Properties
Returned by readFile(), this class holds the loaded content:
Prop
Type
VirtualFile Methods
Prop
Type
Example: Conditional Processing
processor.ts
StartProcessorWithLambda(async (input, fileHelper) => {const refs = fileHelper.get({ root: 'templates', glob: '**/*' });const config = input.config as { processMarkdown: boolean };for (const ref of refs) {// Only process markdown files if enabledif (config.processMarkdown && ref.relative.endsWith('.md')) {const file = ref.readFile();file.content = transformMarkdown(file.content);file.writeFile();} else {// Copy other files directly using fileHelper.copy()fileHelper.copy({ root: 'templates', glob: ref.relative });}}return { directory: input.writeDir };});
processor.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 TypedDictclass Config(TypedDict):processMarkdown: boolasync def my_processor(input: ProcessorInput, fileHelper: CyanFileHelper):refs = fileHelper.get(root='templates', glob='**/*')config: Config = input.config or {'processMarkdown': False}for ref in refs:# Only process markdown files if enabledif config.get('processMarkdown') and ref.relative.endswith('.md'):file = ref.read_file()file.content = transform_markdown(file.content)file.write_file()else:# Copy other files directly using fileHelper.copy()fileHelper.copy(root='templates', glob=ref.relative)return {'directory': input.write_directory}start_processor_with_fn(my_processor)
Processor.cs
using sulfone_helium;using sulfone_helium.Domain.Core.FileSystem;using sulfone_helium.Domain.Processor;public class Config{public bool ProcessMarkdown { get; set; }}CyanEngine.StartProcessor(args, async (input, fileHelper) =>{var refs = fileHelper.Get(root: "templates", glob: "**/*");var config = input.Config.Deserialize<Config>() ?? new Config();foreach (var ref_ in refs){// Only process markdown files if enabledif (config.ProcessMarkdown && ref_.Relative.EndsWith(".md")){var file = ref_.ReadFile();file.Content = TransformMarkdown(file.Content);file.WriteFile();}else{// Copy other files directly using fileHelper.Copy()fileHelper.Copy(root: "templates", glob: ref_.Relative);}}return new ProcessorOutput { Directory = input.WriteDirectory };});
Example: Process by Extension
processor.ts
StartProcessorWithLambda(async (input, fileHelper) => {const refs = fileHelper.get({ root: 'assets', glob: '**/*' });for (const ref of refs) {// Process based on file extensionif (ref.relative.endsWith('.json')) {const file = ref.readFile();const data = JSON.parse(file.content);// Transform and write backdata.processed = true;file.content = JSON.stringify(data, null, 2);file.writeFile();} else {// Copy non-JSON files directlyfileHelper.copy({ root: 'assets', glob: ref.relative });}}return { directory: input.writeDir };});
processor.py
import jsonfrom cyanprintsdk import start_processor_with_fnfrom cyanprintsdk.domain.processor.input import ProcessorInputfrom cyanprintsdk.domain.core.fs.cyan_fs_helper import CyanFileHelperasync def my_processor(input: ProcessorInput, fileHelper: CyanFileHelper):refs = fileHelper.get(root='assets', glob='**/*')for ref in refs:# Process based on file extensionif ref.relative.endswith('.json'):file = ref.read_file()data = json.loads(file.content)# Transform and write backdata['processed'] = Truefile.content = json.dumps(data, indent=2)file.write_file()else:# Copy non-JSON files directlyfileHelper.copy(root='assets', glob=ref.relative)return {'directory': input.write_directory}start_processor_with_fn(my_processor)
Processor.cs
using System.Text.Json;using sulfone_helium;using sulfone_helium.Domain.Core.FileSystem;using sulfone_helium.Domain.Processor;CyanEngine.StartProcessor(args, async (input, fileHelper) =>{var refs = fileHelper.Get(root: "assets", glob: "**/*");foreach (var ref_ in refs){// Process based on file extensionif (ref_.Relative.EndsWith(".json")){var file = ref_.ReadFile();var data = JsonSerializer.Deserialize<Dictionary<string, object>>(file.Content);// Transform and write backdata["processed"] = true;file.Content = JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true });file.WriteFile();}else{// Copy non-JSON files directlyfileHelper.Copy(root: "assets", glob: ref_.Relative);}}return new ProcessorOutput { Directory = input.WriteDirectory };});
Lazy loading is memory-efficient because you only load content for files you actually need to process. Files that don't need transformation can be copied directly using fileHelper.copy().
Related
- Resolve All Files - Load all at once
- Copy Files - Copy without loading
- CyanFileHelper API - Full API reference