@jinbacode/core
v0.0.9
Published
Core framework for building type-safe, composable workflow automation with JinbaFlow
Maintainers
Readme
@jinbacode/core
The core framework for building type-safe, composable workflow automation with JinbaFlow.
Installation
npm install @jinbacode/core
# or
pnpm add @jinbacode/coreOverview
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
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
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:
interface Tool<TInput, TOutput> {
description: string;
inputSchema: z.ZodSchema;
outputSchema: z.ZodSchema;
execute: (input: TInput) => Promise<TOutput>;
}Usage
Basic Flow
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
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
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
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
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
// 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:
# 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=jinbacodeError Handling
Flows should handle errors gracefully:
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
- Use Descriptive Schemas: Always add
.describe()to schema fields - Validate Early: Let Zod handle input validation
- Handle Errors: Provide meaningful error messages
- Keep Flows Focused: Each flow should do one thing well
- Use Tools: Leverage pre-built tools from @jinbacode/tools
- Type Safety: Never use
any, leverage TypeScript's type system
Examples
See the @jinbacode/tools package for complete examples:
- CSV processing flows
- AI-powered workflows
- Google Sheets integration
- Web search automation
License
MIT
