LogoCyanPrint
PluginsReferenceSDK Reference

StartPluginWithLambda

Entry point for CyanPrint plugins

StartPluginWithLambda

Register a plugin function that handles post-processing after file generation.

Signature

function StartPluginWithLambda(
handler: (input: CyanPluginInput) => Promise<PluginOutput>
): void;
from atomicloud_cyan_sdk import start_plugin_with_fn
@start_plugin_with_fn
async def handler(input: PluginInput) -> PluginOutput:
...
[PluginMain]
public static async Task<PluginOutput> Main(PluginInput input)
{
// ...
}

Parameters

ParameterTypeDescription
handler(input: CyanPluginInput) => Promise<PluginOutput>Async function that processes the generated files

Usage

Basic

index.ts
import { StartPluginWithLambda } from '@atomicloud/cyan-sdk';
StartPluginWithLambda(async (input) => {
const { directory } = input;
// Your plugin logic here
return { directory };
});
index.py
from atomicloud_cyan_sdk import start_plugin_with_fn, PluginInput, PluginOutput
@start_plugin_with_fn
async def main(input: PluginInput) -> PluginOutput:
directory = input.directory
# Your plugin logic here
return {'directory': directory}
Plugin.cs
using Atomicloud.Cyan.Sdk;
[PluginMain]
public static class Plugin
{
public static async Task<PluginOutput> Main(PluginInput input)
{
var directory = input.Directory;
// Your plugin logic here
return new PluginOutput { Directory = directory };
}
}

With Config

plugin.ts
import { StartPluginWithLambda } from '@atomicloud/cyan-sdk';
import { $ } from 'bun';
interface MyConfig {
git?: boolean;
installDeps?: boolean;
}
StartPluginWithLambda(async (input) => {
const { directory, config } = input;
const cfg = config as MyConfig;
if (cfg.git) {
await $`git -C ${directory} init`.quiet();
}
if (cfg.installDeps) {
await $`cd ${directory} && npm install`.quiet();
}
return { directory };
});
plugin.py
from atomicloud_cyan_sdk import start_plugin_with_fn, PluginInput, PluginOutput
import subprocess
@start_plugin_with_fn
async def main(input: PluginInput) -> PluginOutput:
directory = input.directory
config = input.config
if config.get('git'):
subprocess.run(['git', '-C', directory, 'init'], capture_output=True)
if config.get('installDeps'):
subprocess.run(['npm', 'install', '--prefix', directory], capture_output=True)
return {'directory': directory}
Plugin.cs
using Atomicloud.Cyan.Sdk;
using System.Diagnostics;
using System.Text.Json;
[PluginMain]
public static class Plugin
{
public static async Task<PluginOutput> Main(PluginInput input)
{
var directory = input.Directory;
var config = JsonSerializer.Deserialize<Dictionary<string, object>>(
input.Config.ToString()
);
if (config?.ContainsKey("git") == true && config["git"] is bool git && git)
{
Process.Start("git", $"-C {directory} init")?.WaitForExit();
}
if (config?.ContainsKey("installDeps") == true && config["installDeps"] is bool installDeps && installDeps)
{
Process.Start("npm", $"install --prefix {directory}")?.WaitForExit();
}
return new PluginOutput { Directory = directory };
}
}

Error Handling

StartPluginWithLambda(async (input) => {
const { directory } = input;
try {
// Attempt operation
await $`git -C ${directory} init`.quiet();
} catch (error) {
// Log error but continue
console.error('Git init failed:', error);
}
// Always return directory
return { directory };
});
@start_plugin_with_fn
async def main(input: PluginInput) -> PluginOutput:
directory = input.directory
try:
# Attempt operation
subprocess.run(['git', '-C', directory, 'init'], capture_output=True)
except Exception as error:
# Log error but continue
print(f'Git init failed: {error}')
# Always return directory
return {'directory': directory}
[PluginMain]
public static async Task<PluginOutput> Main(PluginInput input)
{
var directory = input.Directory;
try
{
// Attempt operation
Process.Start("git", $"-C {directory} init")?.WaitForExit();
}
catch (Exception error)
{
// Log error but continue
Console.WriteLine($"Git init failed: {error.Message}");
}
// Always return directory
return new PluginOutput { Directory = directory };
}

How It Works

Plugin starts

Container runs on port 5552

Request received

POST /api/plug with PluginInput

Handler executes

Your async function processes the directory

Response sent

Returns PluginOutput with directory path

Port

Plugins listen on port 5552 by default:

// Internal server starts on port 5552
// Handles: POST /api/plug
# Internal server starts on port 5552
# Handles: POST /api/plug
// Internal server starts on port 5552
// Handles: POST /api/plug

Return Value

Always return the directory path:

StartPluginWithLambda(async (input) => {
const { directory } = input;
// ... plugin logic ...
// Required: return directory
return { directory };
});
@start_plugin_with_fn
async def main(input: PluginInput) -> PluginOutput:
directory = input.directory
# ... plugin logic ...
# Required: return directory
return {'directory': directory}
[PluginMain]
public static async Task<PluginOutput> Main(PluginInput input)
{
var directory = input.Directory;
// ... plugin logic ...
// Required: return directory
return new PluginOutput { Directory = directory };
}