Plugin Input/Output
Type definitions for plugin interfaces
Plugin Input/Output
Type definitions for the data structures passed to and returned from plugins.
CyanPluginInput
The input object passed to the plugin handler.
Definition
types.ts
interface CyanPluginInput {directory: string;config: unknown;}
types.py
from dataclasses import dataclassfrom typing import Any@dataclassclass PluginInput:directory: strconfig: Any
Types.cs
public class PluginInput{public string Directory { get; set; }public object Config { get; set; }}
Properties
Prop
Type
Typical Values
| Property | Typical Value |
|---|---|
directory | /workspace/output/ |
Usage
plugin.ts
import { StartPluginWithLambda, type CyanPluginInput, type PluginOutput } from '@atomicloud/cyan-sdk';StartPluginWithLambda(async (input) => {console.log('Directory:', input.directory);console.log('Config:', input.config);return { directory: input.directory };});
plugin.py
from atomicloud_cyan_sdk import start_plugin_with_fn, PluginInput, PluginOutput@start_plugin_with_fnasync def main(input: PluginInput) -> PluginOutput:print('Directory:', input.directory)print('Config:', input.config)return {'directory': input.directory}
Plugin.cs
using Atomicloud.Cyan.Sdk;[PluginMain]public static class Plugin{public static async Task<PluginOutput> Main(PluginInput input){Console.WriteLine($"Directory: {input.Directory}");Console.WriteLine($"Config: {input.Config}");return new PluginOutput { Directory = input.Directory };}}
PluginOutput
The return value from the plugin handler.
Definition
types.ts
interface PluginOutput {directory: string;}
types.py
from dataclasses import dataclass@dataclassclass PluginOutput:directory: str
Types.cs
public class PluginOutput{public string Directory { get; set; }}
Properties
Prop
Type
Usage
plugin.ts
StartPluginWithLambda(async (input) => {// ... processing ...// Must return the directoryreturn { directory: input.directory };});
plugin.py
@start_plugin_with_fnasync def main(input: PluginInput) -> PluginOutput:# ... processing ...# Must return the directoryreturn {'directory': input.directory}
Plugin.cs
[PluginMain]public static async Task<PluginOutput> Main(PluginInput input){// ... processing ...// Must return the directoryreturn new PluginOutput { Directory = input.Directory };}
Config Type
Type Safety
The config property is typed as unknown. Cast to your expected type for proper type checking.
Definition
config.ts
// Define your config typeinterface MyPluginConfig {git?: boolean;installDeps?: boolean;packageManager?: 'npm' | 'bun' | 'yarn' | 'pnpm';}
config.py
from dataclasses import dataclassfrom typing import Literal, Optional@dataclassclass MyPluginConfig:git: Optional[bool] = NoneinstallDeps: Optional[bool] = NonepackageManager: Optional[Literal['npm', 'bun', 'yarn', 'pnpm']] = None
Config.cs
public class MyPluginConfig{public bool? Git { get; set; }public bool? InstallDeps { get; set; }public string? PackageManager { get; set; } // "npm", "bun", "yarn", "pnpm"}
Config Options
plugin.ts
StartPluginWithLambda(async (input) => {// Cast to your typeconst config = input.config as MyPluginConfig;// Or with defaultsconst configWithDefaults: MyPluginConfig = {git: true,installDeps: false,packageManager: 'npm',...(input.config as Partial<MyPluginConfig>)};if (config.git) {// ...}return { directory: input.directory };});
plugin.py
from atomicloud_cyan_sdk import start_plugin_with_fn, PluginInput, PluginOutput@start_plugin_with_fnasync def main(input: PluginInput) -> PluginOutput:# Cast to your typeconfig = MyPluginConfig(**input.config)# Or with defaultsdefaults = {'git': True, 'installDeps': False, 'packageManager': 'npm'}merged = {**defaults, **input.config}config = MyPluginConfig(**merged)if config.git:# ...return {'directory': input.directory}
Plugin.cs
using Atomicloud.Cyan.Sdk;using System.Text.Json;[PluginMain]public static class Plugin{public static async Task<PluginOutput> Main(PluginInput input){// Cast to your typevar config = JsonSerializer.Deserialize<MyPluginConfig>(input.Config.ToString()) ?? new MyPluginConfig();// Or with defaultsconfig.Git ??= true;config.InstallDeps ??= false;config.PackageManager ??= "npm";if (config.Git == true){// ...}return new PluginOutput { Directory = input.Directory };}}
Complex Config
config.ts
interface PluginConfig {// Simple typesenabled: boolean;timeout: number;outputPath: string;// Arrayscommands: string[];// Nested objectsgit: {init: boolean;initialCommit: boolean;message: string;};// Optional propertiesformatter?: 'prettier' | 'biome';}
config.py
from dataclasses import dataclass, fieldfrom typing import Literal, Optional, List@dataclassclass GitConfig:init: boolinitialCommit: boolmessage: str@dataclassclass PluginConfig:# Simple typesenabled: booltimeout: intoutputPath: str# Arrayscommands: List[str] = field(default_factory=list)# Nested objectsgit: Optional[GitConfig] = None# Optional propertiesformatter: Optional[Literal['prettier', 'biome']] = None
Config.cs
public class GitConfig{public bool Init { get; set; }public bool InitialCommit { get; set; }public string Message { get; set; }}public class PluginConfig{// Simple typespublic bool Enabled { get; set; }public int Timeout { get; set; }public string OutputPath { get; set; }// Arrayspublic List<string> Commands { get; set; } = new();// Nested objectspublic GitConfig? Git { get; set; }// Optional propertiespublic string? Formatter { get; set; } // "prettier" or "biome"}
Full Example
plugin.ts
import { StartPluginWithLambda, type CyanPluginInput, type PluginOutput } from '@atomicloud/cyan-sdk';import { $ } from 'bun';import * as fs from 'fs/promises';import * as path from 'path';// Define your config typeinterface SetupConfig {git?: boolean;installDeps?: boolean;packageManager?: 'npm' | 'bun' | 'yarn' | 'pnpm';createReadme?: boolean;readmeContent?: string;}StartPluginWithLambda(async (input) => {const { directory } = input;// Parse config with defaultsconst config: SetupConfig = {git: true,installDeps: false,packageManager: 'npm',createReadme: true,...(input.config as Partial<SetupConfig>)};// Log input informationconsole.log('Plugin Input:');console.log(' Directory:', directory);console.log(' Config:', JSON.stringify(config, null, 2));// Initialize gitif (config.git) {await $`git -C ${directory} init`.quiet();await $`git -C ${directory} add .`.quiet();}// Install dependenciesif (config.installDeps) {const pm = config.packageManager;await $`cd ${directory} && ${pm} install`.quiet();}// Create READMEif (config.createReadme) {const readmePath = path.join(directory, 'README.md');await fs.writeFile(readmePath, config.readmeContent || '# Project\n');}// Return outputreturn { directory };});
plugin.py
from atomicloud_cyan_sdk import start_plugin_with_fn, PluginInput, PluginOutputimport subprocessimport osfrom dataclasses import dataclass, fieldfrom typing import Literal, Optional@dataclassclass SetupConfig:git: bool = TrueinstallDeps: bool = FalsepackageManager: Literal['npm', 'bun', 'yarn', 'pnpm'] = 'npm'createReadme: bool = TruereadmeContent: str = '# Project\n'@start_plugin_with_fnasync def main(input: PluginInput) -> PluginOutput:directory = input.directory# Parse config with defaultsdefaults = SetupConfig()config = SetupConfig(git=input.config.get('git', defaults.git),installDeps=input.config.get('installDeps', defaults.installDeps),packageManager=input.config.get('packageManager', defaults.packageManager),createReadme=input.config.get('createReadme', defaults.createReadme),readmeContent=input.config.get('readmeContent', defaults.readmeContent))# Log input informationprint('Plugin Input:')print(f' Directory: {directory}')print(f' Config: {config}')# Initialize gitif config.git:subprocess.run(['git', '-C', directory, 'init'], capture_output=True)subprocess.run(['git', '-C', directory, 'add', '.'], capture_output=True)# Install dependenciesif config.installDeps:subprocess.run(['cd', directory, '&&', config.packageManager, 'install'], capture_output=True)# Create READMEif config.createReadme:readme_path = os.path.join(directory, 'README.md')with open(readme_path, 'w') as f:f.write(config.readmeContent)# Return outputreturn {'directory': directory}
Plugin.cs
using Atomicloud.Cyan.Sdk;using System.Diagnostics;using System.Text.Json;public class SetupConfig{public bool Git { get; set; } = true;public bool InstallDeps { get; set; } = false;public string PackageManager { get; set; } = "npm";public bool CreateReadme { get; set; } = true;public string ReadmeContent { get; set; } = "# Project\n";}[PluginMain]public static class Plugin{public static async Task<PluginOutput> Main(PluginInput input){var directory = input.Directory;// Parse config with defaultsvar config = new SetupConfig();if (input.Config != null){var json = JsonDocument.Parse(input.Config.ToString());var root = json.RootElement;if (root.TryGetProperty("git", out var git))config.Git = git.GetBoolean();if (root.TryGetProperty("installDeps", out var installDeps))config.InstallDeps = installDeps.GetBoolean();if (root.TryGetProperty("packageManager", out var pm))config.PackageManager = pm.GetString() ?? "npm";if (root.TryGetProperty("createReadme", out var createReadme))config.CreateReadme = createReadme.GetBoolean();if (root.TryGetProperty("readmeContent", out var readmeContent))config.ReadmeContent = readmeContent.GetString() ?? "# Project\n";}// Log input informationConsole.WriteLine("Plugin Input:");Console.WriteLine($" Directory: {directory}");Console.WriteLine($" Config: Git={config.Git}, InstallDeps={config.InstallDeps}");// Initialize gitif (config.Git){Process.Start("git", $"-C {directory} init")?.WaitForExit();Process.Start("git", $"-C {directory} add .")?.WaitForExit();}// Install dependenciesif (config.InstallDeps){Process.Start(config.PackageManager, $"install --prefix {directory}")?.WaitForExit();}// Create READMEif (config.CreateReadme){var readmePath = Path.Combine(directory, "README.md");await File.WriteAllTextAsync(readmePath, config.ReadmeContent);}// Return outputreturn new PluginOutput { Directory = directory };}}
Related
- StartPluginWithLambda - Entry point
- Types - All type definitions