Skip to content

Library API ​

ScriptIt provides a powerful programmatic API that allows you to integrate script execution into your applications. The library API offers the same features as the CLI with additional programmatic control and event handling.

Overview ​

The ScriptIt library exports a main function createScriptRunner() that returns a configured script runner instance with methods for executing scripts, managing the TUI, and handling events.

typescript
import { createScriptRunner } from '@glyphtek/scriptit'

const runner = await createScriptRunner({
  scriptsDir: './scripts',
  tmpDir: './tmp',
  consoleInterception: true
})

const result = await runner.executeScript('my-script.js')

Installation ​

Install ScriptIt as a dependency in your project:

bash
bun add @glyphtek/scriptit
bash
npm install @glyphtek/scriptit
bash
pnpm add @glyphtek/scriptit
bash
yarn add @glyphtek/scriptit

Main API ​

createScriptRunner(options?) ​

Creates and configures a script runner instance.

typescript
async function createScriptRunner(
  options?: CreateScriptRunnerOptions
): Promise<ScriptRunnerInstance>

Parameters ​

ParameterTypeDescription
optionsCreateScriptRunnerOptionsConfiguration options (optional)

Returns ​

Returns a Promise<ScriptRunnerInstance> with methods for script execution and management.

Configuration Options ​

CreateScriptRunnerOptions ​

typescript
interface CreateScriptRunnerOptions {
  // Directory configuration
  scriptsDir?: string;              // Directory containing scripts
  tmpDir?: string;                  // Temporary files directory
  workingDirectory?: string;        // Set working directory
  
  // Configuration file
  configFile?: string;              // Path to config file
  
  // Environment configuration
  envFiles?: string[];              // Environment files to load
  initialEnv?: Record<string, string | undefined>; // Initial environment variables
  defaultParams?: Record<string, unknown>; // Default parameters
  
  // Script filtering
  excludePatterns?: string[];       // Glob patterns to exclude
  
  // Console configuration
  consoleInterception?: {
    enabled?: boolean;              // Enable console interception
    includeLevel?: boolean;         // Include log level in output
    preserveOriginal?: boolean;     // Preserve original console methods
    useColors?: boolean;            // Enable colored output
  };
}

Configuration Examples ​

Basic Configuration ​

typescript
const runner = await createScriptRunner({
  scriptsDir: './scripts',
  tmpDir: './tmp'
})

Advanced Configuration ​

typescript
const runner = await createScriptRunner({
  // Directory configuration
  scriptsDir: './src/scripts',
  tmpDir: './temp',
  workingDirectory: '/path/to/project',
  
  // Configuration file
  configFile: './scriptit.config.js',
  
  // Environment configuration
  envFiles: ['.env', '.env.local'],
  initialEnv: {
    NODE_ENV: 'development',
    DEBUG: 'true'
  },
  defaultParams: {
    appName: 'My Application',
    version: '1.0.0'
  },
  
  // Script filtering
  excludePatterns: ['*.test.js', '_*', 'helpers/**'],
  
  // Console configuration
  consoleInterception: {
    enabled: true,
    useColors: true,
    includeLevel: false,
    preserveOriginal: false
  }
})

Working Directory Example ​

typescript
// Change working directory before creating runner
const runner = await createScriptRunner({
  workingDirectory: '/path/to/project',
  scriptsDir: './scripts',  // Resolves from workingDirectory
  tmpDir: './tmp'
})

ScriptRunnerInstance ​

The createScriptRunner() function returns a ScriptRunnerInstance with the following interface:

Properties ​

PropertyTypeDescription
configEffectiveConfigResolved configuration
environmentRecord<string, string | undefined>Loaded environment variables

Methods ​

executeScript(scriptPath, executionParams?, customLogger?) ​

Execute a single script with optional parameters and custom logging.

typescript
async executeScript(
  scriptPath: string,
  executionParams?: Record<string, unknown>,
  customLogger?: (message: string) => void
): Promise<ScriptExecutionResult>

Parameters:

ParameterTypeDescription
scriptPathstringPath to script (relative to scriptsDir or absolute)
executionParamsRecord<string, unknown>Execution parameters (optional)
customLogger(message: string) => voidCustom logging function (optional)

Execution Parameters:

typescript
{
  params?: Record<string, unknown>;     // Parameters passed to script
  env?: Record<string, string>;         // Environment variable overrides
  contextOverrides?: Record<string, unknown>; // Context property overrides
}

Examples:

typescript
// Basic execution
const result = await runner.executeScript('hello.js')

// With parameters
const result = await runner.executeScript('process-data.js', {
  params: {
    inputFile: 'data.csv',
    outputDir: './output'
  },
  env: {
    NODE_ENV: 'production'
  }
})

// With custom logger
const logs: string[] = []
const result = await runner.executeScript('script.js', {}, (message) => {
  logs.push(message)
  console.log(`[CUSTOM] ${message}`)
})

listScripts() ​

List all available scripts in the scripts directory.

typescript
async listScripts(): Promise<string[]>

Returns: Array of script paths relative to the scripts directory.

Example:

typescript
const scripts = await runner.listScripts()
console.log('Available scripts:', scripts)
// Output: ['hello.js', 'data/process.ts', 'utils/cleanup.js']

runTUI() ​

Launch the interactive Terminal UI programmatically.

typescript
async runTUI(): Promise<void>

Example:

typescript
// Launch TUI from your application
await runner.runTUI()

Event Methods ​

on(eventName, listener) ​

Register an event listener.

typescript
on<K extends keyof ScriptEventHandler>(
  eventName: K,
  listener: ScriptEventHandler[K]
): ScriptRunnerInstance
off(eventName, listener) ​

Remove an event listener.

typescript
off<K extends keyof ScriptEventHandler>(
  eventName: K,
  listener: ScriptEventHandler[K]
): ScriptRunnerInstance
emit(eventName, ...args) ​

Emit an event (primarily for internal use).

typescript
emit<K extends keyof ScriptEventHandler>(
  eventName: K,
  ...args: Parameters<ScriptEventHandler[K]>
): boolean

Types ​

ScriptExecutionResult ​

Result returned from script execution:

typescript
interface ScriptExecutionResult {
  [key: string]: unknown;
}

Scripts can return any data structure, which will be available in the result.

ScriptEventHandler ​

Event handler type definitions:

typescript
type ScriptEventHandler = {
  'script:beforeExecute': (scriptPath: string, params: Record<string, unknown>) => void;
  'script:afterExecute': (scriptPath: string, result: ScriptExecutionResult) => void;
  'script:error': (scriptPath: string, error: unknown) => void;
  'script:log': (scriptPath: string, message: string) => void;
  'tui:beforeStart': () => void;
  'tui:afterEnd': () => void;
};

Usage Examples ​

Basic Script Execution ​

typescript
import { createScriptRunner } from '@glyphtek/scriptit'

async function runScript() {
  const runner = await createScriptRunner({
    scriptsDir: './scripts',
    tmpDir: './tmp'
  })

  try {
    const result = await runner.executeScript('hello.js')
    console.log('Script result:', result)
  } catch (error) {
    console.error('Script failed:', error.message)
  }
}

runScript()

Event Handling ​

typescript
import { createScriptRunner } from '@glyphtek/scriptit'

async function runWithEvents() {
  const runner = await createScriptRunner({
    scriptsDir: './scripts',
    tmpDir: './tmp'
  })

  // Register event listeners
  runner.on('script:beforeExecute', (scriptPath, params) => {
    console.log(`Starting script: ${scriptPath}`)
    console.log('Parameters:', params)
  })

  runner.on('script:afterExecute', (scriptPath, result) => {
    console.log(`Script completed: ${scriptPath}`)
    console.log('Result:', result)
  })

  runner.on('script:error', (scriptPath, error) => {
    console.error(`Script failed: ${scriptPath}`)
    console.error('Error:', error)
  })

  runner.on('script:log', (scriptPath, message) => {
    console.log(`[${scriptPath}] ${message}`)
  })

  // Execute script
  await runner.executeScript('example.js')
}

runWithEvents()

Batch Script Execution ​

typescript
import { createScriptRunner } from '@glyphtek/scriptit'

async function runBatch() {
  const runner = await createScriptRunner({
    scriptsDir: './scripts',
    tmpDir: './tmp'
  })

  // Get all available scripts
  const scripts = await runner.listScripts()
  console.log(`Found ${scripts.length} scripts`)

  // Execute scripts in sequence
  for (const script of scripts) {
    try {
      console.log(`\nExecuting: ${script}`)
      const result = await runner.executeScript(script)
      console.log(`✅ Success:`, result)
    } catch (error) {
      console.error(`❌ Failed:`, error.message)
    }
  }
}

runBatch()

Custom Environment and Parameters ​

typescript
import { createScriptRunner } from '@glyphtek/scriptit'

async function runWithCustomEnv() {
  const runner = await createScriptRunner({
    scriptsDir: './scripts',
    tmpDir: './tmp',
    initialEnv: {
      API_URL: 'https://api.example.com',
      DEBUG: 'true'
    },
    defaultParams: {
      appName: 'My App',
      version: '1.0.0'
    }
  })

  const result = await runner.executeScript('deploy.js', {
    params: {
      environment: 'staging',
      dryRun: false
    },
    env: {
      DEPLOY_KEY: process.env.DEPLOY_KEY
    }
  })

  console.log('Deployment result:', result)
}

runWithCustomEnv()

Integration with Express.js ​

typescript
import express from 'express'
import { createScriptRunner } from '@glyphtek/scriptit'

const app = express()
app.use(express.json())

// Initialize script runner
const runner = await createScriptRunner({
  scriptsDir: './api-scripts',
  tmpDir: './tmp',
  consoleInterception: {
    enabled: true,
    useColors: false  // Disable colors for API logs
  }
})

// API endpoint to execute scripts
app.post('/api/scripts/:scriptName', async (req, res) => {
  try {
    const { scriptName } = req.params
    const { params, env } = req.body

    const result = await runner.executeScript(scriptName, {
      params,
      env
    })

    res.json({
      success: true,
      result
    })
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    })
  }
})

// API endpoint to list available scripts
app.get('/api/scripts', async (req, res) => {
  try {
    const scripts = await runner.listScripts()
    res.json({ scripts })
  } catch (error) {
    res.status(500).json({ error: error.message })
  }
})

app.listen(3000, () => {
  console.log('API server running on port 3000')
})

TypeScript Integration ​

typescript
import { createScriptRunner, type ScriptExecutionResult } from '@glyphtek/scriptit'

interface DeploymentResult {
  success: boolean
  deployedFiles: string[]
  duration: number
}

async function deployApp(): Promise<DeploymentResult> {
  const runner = await createScriptRunner({
    scriptsDir: './deployment-scripts',
    tmpDir: './tmp'
  })

  const result: ScriptExecutionResult = await runner.executeScript('deploy.ts', {
    params: {
      environment: 'production',
      version: '1.2.0'
    }
  })

  // Type assertion for known script result structure
  return result as DeploymentResult
}

deployApp().then(result => {
  console.log(`Deployment ${result.success ? 'succeeded' : 'failed'}`)
  console.log(`Files deployed: ${result.deployedFiles.length}`)
  console.log(`Duration: ${result.duration}ms`)
})

Error Handling and Retry Logic ​

typescript
import { createScriptRunner } from '@glyphtek/scriptit'

async function runWithRetry(scriptPath: string, maxRetries = 3) {
  const runner = await createScriptRunner({
    scriptsDir: './scripts',
    tmpDir: './tmp'
  })

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      console.log(`Attempt ${attempt}/${maxRetries}: ${scriptPath}`)
      
      const result = await runner.executeScript(scriptPath)
      console.log('✅ Success:', result)
      return result
      
    } catch (error) {
      console.error(`❌ Attempt ${attempt} failed:`, error.message)
      
      if (attempt === maxRetries) {
        throw new Error(`Script failed after ${maxRetries} attempts: ${error.message}`)
      }
      
      // Wait before retry
      await new Promise(resolve => setTimeout(resolve, 1000 * attempt))
    }
  }
}

runWithRetry('flaky-script.js')
  .then(result => console.log('Final result:', result))
  .catch(error => console.error('All attempts failed:', error.message))

Configuration File Integration ​

The library can load configuration from files just like the CLI:

typescript
// scriptit.config.js
export default {
  scriptsDir: './src/scripts',
  tmpDir: './temp',
  envFiles: ['.env', '.env.local'],
  excludePatterns: ['*.test.js', '_*'],
  defaultParams: {
    appName: 'My Application'
  }
}
typescript
// Use configuration file
const runner = await createScriptRunner({
  configFile: './scriptit.config.js',
  // Override specific options
  initialEnv: {
    NODE_ENV: 'development'
  }
})

Best Practices ​

1. Error Handling ​

Always wrap script execution in try-catch blocks:

typescript
try {
  const result = await runner.executeScript('script.js')
  // Handle success
} catch (error) {
  // Handle error
  console.error('Script execution failed:', error.message)
}

2. Event Monitoring ​

Use events for monitoring and logging:

typescript
runner.on('script:beforeExecute', (scriptPath) => {
  console.log(`Starting: ${scriptPath}`)
})

runner.on('script:error', (scriptPath, error) => {
  // Log to monitoring service
  logger.error('Script failed', { scriptPath, error })
})

3. Resource Management ​

Clean up resources when done:

typescript
// If you need to clean up (future feature)
// await runner.close()

4. Type Safety ​

Use TypeScript for better type safety:

typescript
import type { ScriptExecutionResult } from '@glyphtek/scriptit'

interface MyScriptResult {
  processedCount: number
  errors: string[]
}

const result = await runner.executeScript('my-script.ts') as MyScriptResult

Released under the MIT License.