npm package: @jinbacode/core
Description: Core framework for building type-safe, composable workflow automation with JinbaFlow
Author: Carnot Tech
Latest version: 0.0.9

# @jinbacode/core

The core framework for building type-safe, composable workflow automation with JinbaFlow.

## Installation

```bash
npm install @jinbacode/core
# or
pnpm add @jinbacode/core
```

## Overview

JinbaFlow Core provides the fundamental building blocks for creating workflow automation:

- **Flow Definition**: Type-safe workflow definitions with input/output validation
- **Context Management**: Secure access to storage and secrets
- **Tool Interface**: Standard interface for building reusable tools
- **Execution Engine**: Safe workflow execution with error handling

## Core Concepts

### Flow

A Flow is the basic unit of work in JinbaFlow. Each flow has:
- Unique ID and name
- Input/output schemas (using Zod)
- Execution function with context access

```typescript
import { type Flow } from "@jinbacode/core";
import { z } from "zod";

const myFlow: Flow<z.ZodSchema, z.ZodSchema> = {
  id: "my-flow",
  name: "My Flow",
  inputSchema: z.object({
    message: z.string().describe("Input message"),
  }),
  outputSchema: z.object({
    result: z.string().describe("Processed result"),
  }),
  execute: async (context, input) => {
    // Your flow logic here
    return {
      result: `Processed: ${input.message}`,
    };
  },
};
```

### Context

The context object provides access to:
- **Storage**: S3-compatible file storage
- **Secrets**: Environment variables and API keys

```typescript
execute: async (context, input) => {
  // Access storage
  const file = await context.storage?.get("file-id");
  
  // Access secrets
  const apiKey = context.secret?.OPENAI_API_KEY;
  
  // Your logic here
}
```

### Tools

Tools are reusable functions that follow the standard interface:

```typescript
interface Tool<TInput, TOutput> {
  description: string;
  inputSchema: z.ZodSchema;
  outputSchema: z.ZodSchema;
  execute: (input: TInput) => Promise<TOutput>;
}
```

## Usage

### Basic Flow

```typescript
import { type Flow, executeFlowDefault } from "@jinbacode/core";
import { z } from "zod";

const greetingFlow: Flow<z.ZodSchema, z.ZodSchema> = {
  id: "greeting",
  name: "Greeting Flow",
  inputSchema: z.object({
    name: z.string(),
  }),
  outputSchema: z.object({
    greeting: z.string(),
  }),
  execute: async (ctx, input) => {
    return {
      greeting: `Hello, ${input.name}!`,
    };
  },
};

// Execute the flow
const result = await executeFlowDefault(greetingFlow, { name: "Alice" });
console.log(result.greeting); // "Hello, Alice!"
```

### Flow with Storage

```typescript
const fileProcessingFlow: Flow<z.ZodSchema, z.ZodSchema> = {
  id: "file-processor",
  name: "File Processing Flow",
  inputSchema: z.object({
    fileId: z.string(),
  }),
  outputSchema: z.object({
    processedFileId: z.string(),
  }),
  execute: async (ctx, input) => {
    // Get file from storage
    const file = await ctx.storage?.get(input.fileId);
    if (!file?.downloadUrl) {
      throw new Error("File not found");
    }
    
    // Process file (example)
    const processedContent = await processFile(file.downloadUrl);
    
    // Save result
    const newFileId = `processed-${Date.now()}`;
    await ctx.storage?.put(newFileId, processedContent);
    
    return {
      processedFileId: newFileId,
    };
  },
};
```

### Flow with Tools

```typescript
import { csvTools } from "@jinbacode/tools";

const dataAnalysisFlow: Flow<z.ZodSchema, z.ZodSchema> = {
  id: "data-analysis",
  name: "Data Analysis Flow",
  inputSchema: z.object({
    csvUrl: z.string().url(),
  }),
  outputSchema: z.object({
    rowCount: z.number(),
    summary: z.string(),
  }),
  execute: async (ctx, input) => {
    const { readCsvFromUrl } = csvTools();
    
    // Read CSV data
    const { rows } = await readCsvFromUrl.execute({
      url: input.csvUrl,
    });
    
    // Analyze data
    const summary = analyzeData(rows);
    
    return {
      rowCount: rows.length,
      summary,
    };
  },
};
```

## API Reference

### Flow Interface

```typescript
interface Flow<TInputSchema extends z.ZodSchema, TOutputSchema extends z.ZodSchema> {
  id: string;
  name: string;
  inputSchema: TInputSchema;
  outputSchema: TOutputSchema;
  execute: (
    context: Context,
    input: z.infer<TInputSchema>
  ) => Promise<z.infer<TOutputSchema>>;
}
```

### Context Interface

```typescript
interface Context {
  storage?: Storage;
  secret?: Record<string, string>;
}

interface Storage {
  get(key: string): Promise<{ downloadUrl: string } | null>;
  put(key: string, file: Buffer | string, options?: StorageOptions): Promise<{ downloadUrl: string }>;
  delete(key: string): Promise<void>;
  list(prefix?: string): Promise<StorageObject[]>;
}
```

### Execution Functions

```typescript
// Execute with custom context
async function executeFlow<T extends Flow<z.ZodSchema, z.ZodSchema>>(
  flow: T,
  input: z.infer<T["inputSchema"]>,
  context: Context
): Promise<z.infer<T["outputSchema"]>>

// Execute with default context
async function executeFlowDefault<T extends Flow<z.ZodSchema, z.ZodSchema>>(
  flow: T,
  input: z.infer<T["inputSchema"]>
): Promise<z.infer<T["outputSchema"]>>
```

## Storage Configuration

JinbaFlow uses S3-compatible storage. Configure with environment variables:

```env
# AWS S3
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_REGION=us-east-1
S3_BUCKET=your-bucket

# MinIO (local development)
S3_ENDPOINT=http://localhost:9000
S3_BUCKET=jinbacode
```

## Error Handling

Flows should handle errors gracefully:

```typescript
execute: async (ctx, input) => {
  try {
    // Your logic
  } catch (error) {
    // Log error for debugging
    console.error("Flow error:", error);
    
    // Throw with meaningful message
    throw new Error(`Failed to process: ${error.message}`);
  }
}
```

## Best Practices

1. **Use Descriptive Schemas**: Always add `.describe()` to schema fields
2. **Validate Early**: Let Zod handle input validation
3. **Handle Errors**: Provide meaningful error messages
4. **Keep Flows Focused**: Each flow should do one thing well
5. **Use Tools**: Leverage pre-built tools from @jinbacode/tools
6. **Type Safety**: Never use `any`, leverage TypeScript's type system

## Examples

See the [@jinbacode/tools](../tools) package for complete examples:
- CSV processing flows
- AI-powered workflows
- Google Sheets integration
- Web search automation

## License

MIT