synthase
Version:
A secure, sandboxed, and extensible JavaScript execution engine built with TypeScript.
536 lines (527 loc) • 15.2 kB
text/typescript
interface ParameterDef {
type: "int" | "float" | "string" | "boolean" | "object" | "array";
default?: any;
min?: number;
max?: number;
step?: number;
options?: any[];
itemType?: string;
description?: string;
placeholder?: string;
group?: string;
dependsOn?: Record<string, any>;
}
interface ContextProvider {
[key: string]: any;
}
interface SynthaseConfig {
registry?: ScriptRegistry;
limits?: ExecutionLimitsConfig;
resourceMonitor?: ResourceMonitorConfig;
cachePolicy?: {
maxAge?: number;
maxSize?: number;
};
contextProviders?: ContextProvider;
}
interface ScriptRegistry {
resolve(scriptId: string): Promise<string>;
}
interface LoadedScript {
id: string;
io: IOSchema;
deps: string[];
defaultFunction: Function;
}
type ParameterSpec = string | ParameterDef;
interface IOSchema {
inputs: Record<string, ParameterSpec>;
outputs: Record<string, ParameterSpec>;
}
type ScriptContentResolver = () => Promise<string>;
interface ExecutionContext {
Logger: {
info: (message: string) => void;
success: (message: string) => void;
warn: (message: string) => void;
error: (message: string) => void;
};
Calculator: {
enhance: (value: number) => number;
sum: (array: number[]) => number;
average: (array: number[]) => number;
multiply: (numbers: number[]) => number;
};
Utils: {
formatNumber: (num: number, decimals?: number) => number;
capitalize: (str: string) => string;
delay: (ms: number) => Promise<void>;
randomInt: (min: number, max: number) => number;
shuffleArray: (array: any[]) => any[];
randomChoice: (array: any[]) => any;
};
/**
* Import script function that returns callable script
*/
importScript: (contentOrResolver: string | ScriptContentResolver) => Promise<ImportedScript>;
}
interface ImportedScript {
(inputs: Record<string, any>): Promise<any>;
io: IOSchema;
deps: string[];
id: string;
}
interface ImportedScript {
(inputs: Record<string, any>): Promise<any>;
io: IOSchema;
deps: string[];
id: string;
}
interface ValidationResult {
valid: boolean;
errors: string[];
warnings?: string[];
}
interface CacheEntry {
script: LoadedScript;
timestamp: number;
contentHash: string;
source: string;
}
interface CacheEntry {
script: LoadedScript;
timestamp: number;
contentHash: string;
source: string;
}
interface ResourceStats {
memoryUsed: number;
maxMemoryUsed: number;
memoryLimit: number;
memoryPercentage: number;
duration: number;
checksPerformed: number;
}
interface ExecutionLimitsConfig {
timeout?: number;
maxRecursionDepth?: number;
maxImportedScripts?: number;
maxMemory?: number;
}
interface ResourceMonitorConfig {
maxMemory?: number;
checkIntervalMs?: number;
}
declare class ParameterUtils {
static normalize(spec: ParameterSpec): ParameterDef;
static getDefault(spec: ParameterSpec): any;
static applyDefaults(inputs: Record<string, any>, schema: Record<string, ParameterSpec>): Record<string, any>;
static validateParameter(value: any, spec: ParameterSpec, paramName: string): void;
static shouldShowParameter(spec: ParameterSpec, allInputs: Record<string, any>): boolean;
static groupParameters(schema: Record<string, ParameterSpec>): Record<string, string[]>;
}
declare class Synthase {
private scriptContentOrResolver;
private config?;
private scriptCache;
private cachePolicy;
private loadedScript;
private isInitialized;
private initializationPromise;
private executionLimits;
private scriptValidator;
private resourceMonitor;
private registry?;
constructor(scriptContentOrResolver: string | ScriptContentResolver, config?: SynthaseConfig | undefined);
/**
* Configure cache policy
*/
setCachePolicy(policy: Partial<typeof this.cachePolicy>): void;
/**
* Wait for initialization to complete
*/
waitForInitialization(): Promise<void>;
/**
* Initialize and plan the main script
*/
private initialize;
/**
* Execute the script with given inputs
*/
call(inputs: Record<string, any>): Promise<any>;
/**
* Get the IO schema of the loaded script
*/
getIO(): IOSchema | null;
/**
* Get dependencies of the loaded script
*/
getDependencies(): string[];
/**
* Reload the script (for hot reloading)
*/
reload(): Promise<void>;
/**
* Load script and all dependencies
*/
private loadScriptTree;
/**
* Create execution context with injectable dependencies
*/
private createExecutionContext;
/**
* Process script content into LoadedScript
*/
private processScript;
/**
* Validate inputs against IO schema
*/
private validateInputs;
/**
* Check if script is cached and still valid
*/
private getCachedScript;
/**
* Cache a processed script
*/
private cacheScript;
/**
* Invalidate cache for a specific script
*/
invalidateScript(scriptId: string): void;
/**
* Invalidate cache by content (call this when script content changes)
*/
invalidateByContent(scriptId: string, newContent: string): void;
/**
* Clean up old cache entries
*/
private cleanupCache;
/**
* Get cache statistics
*/
getCacheStats(): {
totalEntries: number;
avgAge: number;
sources: Record<string, number>;
};
/**
* Better content hashing for cache invalidation
*/
private hashContent;
/**
* Clear all caches
*/
clearCache(): void;
/**
* Create module from script content
*/
private createModule;
/**
* Introspect module to extract IO, dependencies, and default function
* Fixed version that properly imports the module to preserve function scope
*/
private introspectModule;
/**
* Extract dependencies from script content
*/
private extractDependencies;
/**
* Dispose resources
*/
dispose(): void;
}
/**
* Configuration options for quick execution (now extends SynthaseConfig)
*/
interface QuickExecuteOptions extends SynthaseConfig {
strict?: boolean;
}
/**
* Quick execute: plan and run a script in one call
* This is a convenience wrapper for API endpoints and simple usage
*/
declare function execute$1(scriptContentOrResolver: string | ScriptContentResolver, inputs: Record<string, any>, options?: QuickExecuteOptions): Promise<any>;
/**
* Validate script without executing it
*/
declare function validate$1(scriptContentOrResolver: string | ScriptContentResolver, options?: QuickExecuteOptions): Promise<{
valid: boolean;
io: any;
dependencies: string[];
errors?: string[];
}>;
/**
* Execute with validation - validates inputs against schema before execution
*/
declare function executeWithValidation$1(scriptContentOrResolver: string | ScriptContentResolver, inputs: Record<string, any>, options?: QuickExecuteOptions): Promise<any>;
/**
* Batch execute multiple scripts
*/
declare function executeBatch$1(scripts: Array<{
content: string | ScriptContentResolver;
inputs: Record<string, any>;
id?: string;
}>, options?: QuickExecuteOptions): Promise<Array<{
id?: string;
success: boolean;
result?: any;
error?: string;
}>>;
/**
* Create a reusable Synthase instance with caching
* Useful when you want to execute the same script multiple times with different inputs
*/
declare function createReusable$1(scriptContentOrResolver: string | ScriptContentResolver, options?: QuickExecuteOptions): Promise<{
synthase: Synthase;
execute: (inputs: Record<string, any>) => Promise<any>;
getIO: () => any;
getDependencies: () => string[];
dispose: () => void;
}>;
/**
* Hot reload helper - useful for development
*/
declare function createHotReloadable$1(getScript: () => string | ScriptContentResolver, options?: QuickExecuteOptions): Promise<{
execute: (inputs: Record<string, any>) => Promise<any>;
reload: () => Promise<void>;
getIO: () => any;
dispose: () => void;
}>;
/**
* Performance benchmark helper
*/
declare function benchmark$1(scriptContentOrResolver: string | ScriptContentResolver, inputs: Record<string, any>, iterations?: number, options?: QuickExecuteOptions): Promise<{
averageTime: number;
minTime: number;
maxTime: number;
times: number[];
results: any[];
}>;
/**
* Legacy class export for backward compatibility
* @deprecated Use individual functions instead
*/
declare const SynthaseUtils: {
execute: typeof execute$1;
executeWithValidation: typeof executeWithValidation$1;
validate: typeof validate$1;
executeBatch: typeof executeBatch$1;
createReusable: typeof createReusable$1;
createHotReloadable: typeof createHotReloadable$1;
benchmark: typeof benchmark$1;
};
/**
* Manages execution limits and timeouts for script execution
*/
declare class ExecutionLimits {
readonly timeout: number;
readonly maxRecursionDepth: number;
readonly maxImportedScripts: number;
readonly maxMemory: number;
constructor(limits?: Partial<{
timeout: number;
maxRecursionDepth: number;
maxImportedScripts: number;
maxMemory: number;
}>);
/**
* Execute a function with timeout protection
*/
executeWithTimeout<T>(fn: () => Promise<T>, timeoutMs?: number): Promise<T>;
/**
* Check if recursion depth is within limits
*/
checkRecursionDepth(currentDepth: number): void;
/**
* Check if import count is within limits
*/
checkImportCount(currentCount: number): void;
/**
* Update limits configuration
*/
updateLimits(newLimits: Partial<{
timeout: number;
maxRecursionDepth: number;
maxImportedScripts: number;
maxMemory: number;
}>): void;
}
/**
* Validates script content for safety and correctness
*/
declare class ScriptValidator {
private dangerousPatterns;
private requiredPatterns;
/**
* Remove comments from code
*/
private stripComments;
/**
* Replace string content with spaces to maintain structure
*/
private maskStrings;
/**
* Validate script content
*/
validateScript(content: string): {
valid: boolean;
errors: string[];
warnings: string[];
};
/**
* Validate script structure
*/
private validateStructure;
/**
* Check if quotes are properly matched in code
*/
private hasMatchedQuotes;
/**
* Validate IO schema structure
*/
private validateIOSchema;
/**
* Validate parameter definitions in IO schema
*/
private validateParameterDefinitions;
/**
* Check brace balance in code
*/
private checkBraceBalance;
/**
* Get maximum nesting level in code
*/
private getMaxNestingLevel;
/**
* Add custom validation rule
*/
addDangerousPattern(pattern: RegExp, message: string): void;
/**
* Remove validation rule
*/
removeDangerousPattern(message: string): void;
}
/**
* Monitors resource usage during script execution
*/
declare class ResourceMonitor {
private startMemory;
private startTime;
private maxMemoryUsed;
private checkInterval;
private memoryCheckCount;
private readonly maxMemory;
private readonly checkIntervalMs;
constructor(options?: {
maxMemory?: number;
checkIntervalMs?: number;
});
/**
* Start monitoring resources
*/
start(): void;
/**
* Stop monitoring resources
*/
stop(): void;
/**
* Manual memory check (can be called during execution)
*/
check(): void;
/**
* Get current memory usage statistics
*/
getStats(): {
memoryUsed: number;
maxMemoryUsed: number;
memoryLimit: number;
memoryPercentage: number;
duration: number;
checksPerformed: number;
};
/**
* Dispose of resources
*/
dispose(): void;
/**
* Perform a memory check
*/
private performMemoryCheck;
/**
* Get current memory usage
*/
private getCurrentMemoryUsed;
/**
* Check if memory API is available
*/
private isMemoryAPIAvailable;
/**
* Force garbage collection if available (for testing)
*/
forceGC(): void;
/**
* Create a memory pressure test
*/
static createMemoryPressureTest(sizeInMB?: number): () => void;
}
declare class InMemoryScriptRegistry implements ScriptRegistry {
private scripts;
/**
* Register a script with content
*/
register(scriptId: string, content: string): void;
/**
* Resolve script ID to content
*/
resolve(scriptId: string): Promise<string>;
/**
* List all registered scripts
*/
list(): string[];
/**
* Check if script exists
*/
has(scriptId: string): boolean;
/**
* Remove a script
*/
unregister(scriptId: string): boolean;
/**
* Clear all scripts
*/
clear(): void;
}
/**
* HTTP-based script registry for loading from URLs
*/
declare class HttpScriptRegistry implements ScriptRegistry {
private baseUrl?;
constructor(baseUrl?: string | undefined);
resolve(scriptId: string): Promise<string>;
}
/**
* Composite registry that tries multiple sources in order
*/
declare class CompositeScriptRegistry implements ScriptRegistry {
private registries;
constructor(registries: ScriptRegistry[]);
/**
* Add a registry to the end of the list
*/
addRegistry(registry: ScriptRegistry): void;
/**
* Add a registry to the beginning of the list (higher priority)
*/
prependRegistry(registry: ScriptRegistry): void;
resolve(scriptId: string): Promise<string>;
}
declare const VERSION = "2.0.0";
declare const execute: typeof execute$1;
declare const executeWithValidation: typeof executeWithValidation$1;
declare const validate: typeof validate$1;
declare const executeBatch: typeof executeBatch$1;
declare const createReusable: typeof createReusable$1;
declare const createHotReloadable: typeof createHotReloadable$1;
declare const benchmark: typeof benchmark$1;
export { type CacheEntry, CompositeScriptRegistry, type ExecutionContext, ExecutionLimits, type ExecutionLimitsConfig, HttpScriptRegistry, type IOSchema, type ImportedScript, InMemoryScriptRegistry, type LoadedScript, type ParameterDef, type ParameterSpec, ParameterUtils, type QuickExecuteOptions, ResourceMonitor, type ResourceMonitorConfig, type ResourceStats, type ScriptContentResolver, type ScriptRegistry, ScriptValidator, Synthase, SynthaseUtils, VERSION, type ValidationResult, benchmark, createHotReloadable, createReusable, Synthase as default, execute, executeBatch, executeWithValidation, validate };