├── packages ├── backend │ ├── src │ │ ├── queue │ │ │ ├── QueueManager.ts │ │ │ └── WorkflowQueue.ts │ │ ├── workflow │ │ │ ├── WorkflowExecute.ts │ │ │ ├── dto │ │ │ │ ├── update-workflow.dto.ts │ │ │ │ └── create-workflow.dto.ts │ │ │ ├── workflow.module.ts │ │ │ ├── workflow.controller.ts │ │ │ ├── workflow-execution.service.ts │ │ │ ├── workflow-executor.service.ts │ │ │ ├── workflow.processor.ts │ │ │ └── WorkflowRunner.ts │ │ ├── nodes │ │ │ ├── execute_node_function.ts │ │ │ ├── nodes.module.ts │ │ │ ├── base │ │ │ │ ├── BaseNode.ts │ │ │ │ ├── NodeType.ts │ │ │ │ └── NodeFactory.ts │ │ │ ├── trigger │ │ │ │ └── execute-trigger.node.ts │ │ │ ├── transform │ │ │ │ ├── function.node.ts │ │ │ │ ├── merge-data.node.ts │ │ │ │ └── If.node.ts │ │ │ ├── input │ │ │ │ └── rss-feed-read.node.ts │ │ │ ├── organization │ │ │ │ └── split-in-batches.node.ts │ │ │ ├── nodes.controller.ts │ │ │ ├── nodes.service.ts │ │ │ └── node-database.ts │ │ ├── prisma │ │ │ ├── prisma.module.ts │ │ │ └── prisma.service.ts │ │ ├── app.module.ts │ │ └── main.ts │ ├── prisma │ │ ├── migrations │ │ │ ├── migration_lock.toml │ │ │ ├── 20250226160902_remove_node_types │ │ │ │ └── migration.sql │ │ │ └── 20250224215352_initial_table │ │ │ │ └── migration.sql │ │ └── schema.prisma │ ├── config │ │ ├── queue.config.ts │ │ └── database.config.ts │ ├── nest-cli.json │ ├── .env.example │ ├── tsconfig.json │ └── package.json ├── frontend │ ├── postcss.config.cjs │ ├── src │ │ ├── icon │ │ │ ├── index.tsx │ │ │ ├── retry.svg │ │ │ └── test.svg │ │ ├── lib │ │ │ ├── utils.ts │ │ │ ├── icons.ts │ │ │ ├── use-mobile.tsx │ │ │ ├── icons.tsx │ │ │ └── api.ts │ │ ├── env.d.ts │ │ ├── store │ │ │ ├── hooks.ts │ │ │ ├── store.ts │ │ │ ├── workflowSlice.ts │ │ │ └── workflow.store.ts │ │ ├── components │ │ │ ├── ui │ │ │ │ ├── skeleton.tsx │ │ │ │ ├── collapsible.tsx │ │ │ │ ├── textarea.tsx │ │ │ │ ├── label.tsx │ │ │ │ ├── input.tsx │ │ │ │ ├── separator.tsx │ │ │ │ ├── switch.tsx │ │ │ │ ├── tooltip.tsx │ │ │ │ ├── avatar.tsx │ │ │ │ ├── scroll-area.tsx │ │ │ │ ├── button.tsx │ │ │ │ ├── breadcrumb.tsx │ │ │ │ ├── dialog.tsx │ │ │ │ ├── sheet.tsx │ │ │ │ ├── form.tsx │ │ │ │ ├── select.tsx │ │ │ │ └── log.tsx │ │ │ ├── AppSidebar.tsx │ │ │ ├── NavMain.tsx │ │ │ ├── NavPlatforms.tsx │ │ │ ├── WorkflowNameDialog.tsx │ │ │ ├── TeamSwitcher.tsx │ │ │ ├── nodes │ │ │ │ └── NodeComponent.tsx │ │ │ ├── NavUser.tsx │ │ │ ├── NodeList.tsx │ │ │ └── NodeSettings.tsx │ │ ├── main.tsx │ │ ├── auth │ │ │ ├── supabase │ │ │ │ ├── supabaseClient.ts │ │ │ │ └── authService.ts │ │ │ ├── PrivateRoute.tsx │ │ │ ├── Callback.tsx │ │ │ ├── AuthContext.tsx │ │ │ ├── CheckEmail.tsx │ │ │ ├── Login.tsx │ │ │ └── Signup.tsx │ │ ├── pages │ │ │ ├── style.css │ │ │ ├── Executions.tsx │ │ │ └── WorkflowList.tsx │ │ ├── layout │ │ │ └── index.tsx │ │ ├── App.tsx │ │ └── styles │ │ │ └── globals.css │ ├── @workflow-automation │ │ └── common │ │ │ └── lib │ │ │ └── utils.ts │ ├── tsconfig.node.json │ ├── public │ │ └── vite.svg │ ├── index.html │ ├── .eslintrc.cjs │ ├── components.json │ ├── vite.config.ts │ ├── tsconfig.json │ ├── package.json │ ├── tailwind.config.cjs │ ├── vite.config.ts.timestamp-1739526969468-e15a04e20dbba.mjs │ ├── vite.config.ts.timestamp-1739765038470-76e4674c298f.mjs │ ├── vite.config.ts.timestamp-1740531317600-416703792b56.mjs │ ├── vite.config.ts.timestamp-1739917904138-eb6450026d934.mjs │ ├── vite.config.ts.timestamp-1739988195240-f54af25a8de61.mjs │ └── vite.config.ts.timestamp-1740439986678-8181315a6ebc3.mjs └── common │ ├── src │ ├── index.ts │ ├── interfaces │ │ └── IWorkflow.ts │ └── types │ │ ├── execution.types.ts │ │ ├── workflow.types.ts │ │ └── node.types.ts │ ├── tsconfig.json │ └── package.json ├── .vscode └── launch.json ├── package.json └── .gitignore /packages/backend/src/queue/QueueManager.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/backend/src/queue/WorkflowQueue.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/backend/src/workflow/WorkflowExecute.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/backend/src/nodes/execute_node_function.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/frontend/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /packages/frontend/src/icon/index.tsx: -------------------------------------------------------------------------------- 1 | import TestSvg from "./test.svg"; 2 | import RetrySvg from "./retry.svg"; 3 | 4 | export { TestSvg, RetrySvg }; 5 | -------------------------------------------------------------------------------- /packages/common/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './types/node.types'; 2 | export * from './types/workflow.types'; 3 | export * from './types/execution.types'; 4 | -------------------------------------------------------------------------------- /packages/backend/prisma/migrations/migration_lock.toml: -------------------------------------------------------------------------------- 1 | # Please do not edit this file manually 2 | # It should be added in your version-control system (e.g., Git) 3 | provider = "postgresql" -------------------------------------------------------------------------------- /packages/frontend/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /packages/frontend/@workflow-automation/common/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /packages/backend/src/workflow/dto/update-workflow.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/mapped-types'; 2 | import { CreateWorkflowDto } from './create-workflow.dto'; 3 | 4 | export class UpdateWorkflowDto extends PartialType(CreateWorkflowDto) {} 5 | -------------------------------------------------------------------------------- /packages/frontend/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | interface ImportMetaEnv { 4 | readonly VITE_SUPABASE_URL: string 5 | readonly VITE_SUPABASE_KEY: string 6 | } 7 | 8 | interface ImportMeta { 9 | readonly env: ImportMetaEnv 10 | } 11 | -------------------------------------------------------------------------------- /packages/backend/prisma/migrations/20250226160902_remove_node_types/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - You are about to drop the `node_types` table. If the table is not empty, all the data it contains will be lost. 5 | 6 | */ 7 | -- DropTable 8 | DROP TABLE "node_types"; 9 | -------------------------------------------------------------------------------- /packages/backend/src/prisma/prisma.module.ts: -------------------------------------------------------------------------------- 1 | import { Global, Module } from '@nestjs/common'; 2 | import { PrismaService } from './prisma.service'; 3 | 4 | @Global() 5 | @Module({ 6 | providers: [PrismaService], 7 | exports: [PrismaService], 8 | }) 9 | export class PrismaModule {} 10 | -------------------------------------------------------------------------------- /packages/frontend/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/frontend/src/store/hooks.ts: -------------------------------------------------------------------------------- 1 | import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; 2 | import type { RootState, AppDispatch } from './store'; 3 | 4 | export const useAppDispatch: () => AppDispatch = useDispatch; 5 | export const useAppSelector: TypedUseSelectorHook = useSelector; 6 | -------------------------------------------------------------------------------- /packages/backend/src/workflow/dto/create-workflow.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsString, IsArray, IsOptional } from 'class-validator'; 2 | 3 | export class CreateWorkflowDto { 4 | @IsString() 5 | name: string; 6 | 7 | @IsArray() 8 | @IsOptional() 9 | nodes: any[] = []; 10 | 11 | @IsArray() 12 | @IsOptional() 13 | edges: any[] = []; 14 | } 15 | -------------------------------------------------------------------------------- /packages/backend/src/nodes/nodes.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { NodesService } from './nodes.service'; 3 | import { NodesController } from './nodes.controller'; 4 | 5 | @Module({ 6 | controllers: [NodesController], 7 | providers: [NodesService], 8 | exports: [NodesService] 9 | }) 10 | export class NodesModule {} 11 | -------------------------------------------------------------------------------- /packages/backend/config/queue.config.ts: -------------------------------------------------------------------------------- 1 | import { registerAs } from '@nestjs/config'; 2 | 3 | export default registerAs('queue', () => ({ 4 | redis: { 5 | host: process.env.REDIS_HOST || 'localhost', 6 | port: parseInt(process.env.REDIS_PORT, 10) || 6379, 7 | password: process.env.REDIS_PASSWORD, 8 | }, 9 | enabled: process.env.REDIS_ENABLED === 'true', 10 | })); -------------------------------------------------------------------------------- /packages/frontend/src/store/store.ts: -------------------------------------------------------------------------------- 1 | import { configureStore } from '@reduxjs/toolkit'; 2 | import workflowReducer from './workflowSlice'; 3 | 4 | export const store = configureStore({ 5 | reducer: { 6 | workflow: workflowReducer, 7 | }, 8 | }); 9 | 10 | export type RootState = ReturnType; 11 | export type AppDispatch = typeof store.dispatch; 12 | -------------------------------------------------------------------------------- /packages/frontend/src/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "../../lib/utils" 2 | 3 | function Skeleton({ 4 | className, 5 | ...props 6 | }: React.HTMLAttributes) { 7 | return ( 8 |
12 | ) 13 | } 14 | 15 | export { Skeleton } 16 | -------------------------------------------------------------------------------- /packages/common/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "outDir": "./dist", 7 | "strict": true, 8 | "esModuleInterop": true, 9 | "skipLibCheck": true, 10 | "forceConsistentCasingInFileNames": true 11 | }, 12 | "include": ["src"], 13 | "exclude": ["node_modules", "dist"] 14 | } 15 | -------------------------------------------------------------------------------- /packages/frontend/src/components/ui/collapsible.tsx: -------------------------------------------------------------------------------- 1 | import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" 2 | 3 | const Collapsible = CollapsiblePrimitive.Root 4 | 5 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger 6 | 7 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent 8 | 9 | export { Collapsible, CollapsibleTrigger, CollapsibleContent } 10 | -------------------------------------------------------------------------------- /packages/backend/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/nest-cli", 3 | "collection": "@nestjs/schematics", 4 | "sourceRoot": "src", 5 | "entryFile": "backend/src/main", 6 | "compilerOptions": { 7 | "deleteOutDir": true, 8 | "webpack": false, 9 | "tsConfigPath": "tsconfig.json", 10 | "assets": ["**/*.proto"], 11 | "watchAssets": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/frontend/public/vite.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Workflow 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Workflow Automation 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/backend/src/nodes/base/BaseNode.ts: -------------------------------------------------------------------------------- 1 | import { INodeExecutionData } from '@workflow-automation/common'; 2 | 3 | export abstract class BaseNode { 4 | protected settings: Record = {}; 5 | 6 | async onInit(settings: Record): Promise { 7 | this.settings = settings; 8 | } 9 | 10 | getSettings(): Record { 11 | return this.settings; 12 | } 13 | 14 | abstract execute(data: INodeExecutionData[]): Promise; 15 | } 16 | -------------------------------------------------------------------------------- /packages/frontend/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import { Provider } from "react-redux"; 4 | import { store } from "./store/store"; 5 | import App from "./App.tsx"; 6 | import "./styles/globals.css"; 7 | import "reactflow/dist/style.css"; 8 | 9 | ReactDOM.createRoot(document.getElementById("root")!).render( 10 | 11 | 12 | 13 | 14 | 15 | ); 16 | -------------------------------------------------------------------------------- /packages/backend/src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { ConfigModule } from '@nestjs/config'; 3 | import { PrismaModule } from './prisma/prisma.module'; 4 | import { WorkflowModule } from './workflow/workflow.module'; 5 | import { NodesModule } from './nodes/nodes.module'; 6 | 7 | @Module({ 8 | imports: [ 9 | ConfigModule.forRoot({ 10 | isGlobal: true, 11 | }), 12 | PrismaModule, 13 | WorkflowModule, 14 | NodesModule, 15 | ], 16 | }) 17 | export class AppModule {} 18 | -------------------------------------------------------------------------------- /packages/frontend/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:react-hooks/recommended', 8 | ], 9 | ignorePatterns: ['dist', '.eslintrc.cjs'], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['react-refresh'], 12 | rules: { 13 | 'react-refresh/only-export-components': [ 14 | 'warn', 15 | { allowConstantExport: true }, 16 | ], 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /packages/backend/.env.example: -------------------------------------------------------------------------------- 1 | # Database Configuration 2 | DB_TYPE=postgres 3 | DB_HOST=localhost 4 | DB_PORT=5432 5 | DB_USERNAME=postgres 6 | DB_PASSWORD=postgres 7 | DB_DATABASE=workflow_automation 8 | DB_SYNCHRONIZE=true 9 | DB_LOGGING=true 10 | 11 | # Supabase Configuration 12 | SUPABASE_URL=your_supabase_url 13 | SUPABASE_KEY=your_supabase_key 14 | 15 | # Redis Configuration 16 | REDIS_ENABLED=false 17 | REDIS_HOST=localhost 18 | REDIS_PORT=6379 19 | REDIS_PASSWORD= 20 | 21 | # OpenAI Configuration 22 | OPENAI_API_KEY=your_openai_api_key 23 | -------------------------------------------------------------------------------- /packages/frontend/src/auth/supabase/supabaseClient.ts: -------------------------------------------------------------------------------- 1 | import { createClient } from "@supabase/supabase-js"; 2 | 3 | const SUPABASE_URL = import.meta.env.VITE_SUPABASE_URL as string; 4 | const SUPABASE_ANON_KEY = import.meta.env.VITE_SUPABASE_KEY as string; 5 | 6 | export const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, { 7 | auth: { 8 | persistSession: true, // Ensure sessions are persisted 9 | autoRefreshToken: true, // Automatically refresh session tokens 10 | detectSessionInUrl: true, // Useful for OAuth flows 11 | }, 12 | }); 13 | -------------------------------------------------------------------------------- /packages/frontend/src/lib/icons.ts: -------------------------------------------------------------------------------- 1 | import * as LucideIcons from 'lucide-react'; 2 | 3 | // Create a type-safe mapping of icon names to Lucide components 4 | export const iconMap: Record = { 5 | play: LucideIcons.Play, 6 | code: LucideIcons.Code, 7 | split: LucideIcons.Split, 8 | rss: LucideIcons.Rss, 9 | 'git-branch': LucideIcons.GitBranch, 10 | 'git-merge': LucideIcons.GitMerge, 11 | // Add more icons as needed 12 | }; 13 | 14 | // Default icon if the specified icon is not found 15 | export const defaultIcon = LucideIcons.Component; 16 | -------------------------------------------------------------------------------- /packages/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@workflow-automation/common", 3 | "version": "0.0.1", 4 | "private": true, 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "prebuild": "rimraf dist", 9 | "build": "tsc", 10 | "build:watch": "tsc --watch", 11 | "type-check": "tsc --noEmit" 12 | }, 13 | "dependencies": { 14 | "class-transformer": "^0.5.1", 15 | "class-validator": "^0.14.0" 16 | }, 17 | "devDependencies": { 18 | "rimraf": "^5.0.5", 19 | "typescript": "^5.2.2" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/frontend/src/auth/PrivateRoute.tsx: -------------------------------------------------------------------------------- 1 | import { Navigate, Outlet } from "react-router-dom"; 2 | import { useAuth } from "./AuthContext"; 3 | import { useEffect, useState } from "react"; 4 | 5 | export const PrivateRoute = () => { 6 | const { user } = useAuth(); 7 | const [loading, setLoading] = useState(true); 8 | 9 | useEffect(() => { 10 | if (user !== undefined) { 11 | setLoading(false); 12 | } 13 | }, [user]); 14 | 15 | if (loading) { 16 | return

Loading...

; // ✅ Prevents premature redirect 17 | } 18 | 19 | return user ? : ; 20 | }; 21 | -------------------------------------------------------------------------------- /packages/frontend/src/icon/retry.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/frontend/src/lib/use-mobile.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | const MOBILE_BREAKPOINT = 768 4 | 5 | export function useIsMobile() { 6 | const [isMobile, setIsMobile] = React.useState(undefined) 7 | 8 | React.useEffect(() => { 9 | const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) 10 | const onChange = () => { 11 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 12 | } 13 | mql.addEventListener("change", onChange) 14 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 15 | return () => mql.removeEventListener("change", onChange) 16 | }, []) 17 | 18 | return !!isMobile 19 | } 20 | -------------------------------------------------------------------------------- /packages/backend/config/database.config.ts: -------------------------------------------------------------------------------- 1 | import { registerAs } from '@nestjs/config'; 2 | 3 | export default registerAs('database', () => ({ 4 | type: process.env.DB_TYPE || 'postgres', 5 | host: process.env.DB_HOST || 'localhost', 6 | port: parseInt(process.env.DB_PORT, 10) || 5432, 7 | username: process.env.DB_USERNAME || 'postgres', 8 | password: process.env.DB_PASSWORD || 'postgres', 9 | database: process.env.DB_DATABASE || 'workflow_automation', 10 | synchronize: process.env.DB_SYNCHRONIZE === 'true', 11 | logging: process.env.DB_LOGGING === 'true', 12 | supabase: { 13 | url: process.env.SUPABASE_URL, 14 | key: process.env.SUPABASE_KEY, 15 | }, 16 | })); -------------------------------------------------------------------------------- /packages/frontend/src/icon/test.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/frontend/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.cjs", 8 | "css": "src/styles/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@workflow-automation/common/components", 15 | "utils": "@workflow-automation/common/lib/utils", 16 | "ui": "@workflow-automation/common/components/ui", 17 | "lib": "@workflow-automation/common/lib", 18 | "hooks": "@workflow-automation/common/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /packages/frontend/src/lib/icons.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | LucideIcon, 3 | Boxes, 4 | PlayCircle, 5 | Rss, 6 | BrainCircuit, 7 | GitMerge, 8 | SplitSquareVertical, 9 | Code2, 10 | SplitSquareHorizontal 11 | } from 'lucide-react'; 12 | 13 | export const nodeIcons: Record = { 14 | 'manual-trigger': PlayCircle, 15 | 'function': Code2, 16 | 'split-batches': SplitSquareHorizontal, 17 | 'rss-feed': Rss, 18 | 'openai': BrainCircuit, 19 | 'merge': GitMerge, 20 | 'if': SplitSquareVertical, 21 | }; 22 | 23 | export const categoryIcons: Record = { 24 | 'Trigger': PlayCircle, 25 | 'Input': Rss, 26 | 'Transform': Code2, 27 | 'Organization': Boxes, 28 | }; 29 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "node", 6 | "request": "launch", 7 | "name": "Debug Nest Backend", 8 | "runtimeExecutable": "npm", 9 | "runtimeArgs": [ 10 | "run", 11 | "start:debug" 12 | ], 13 | "autoAttachChildProcesses": true, 14 | "restart": true, 15 | "sourceMaps": true, 16 | "stopOnEntry": false, 17 | "console": "integratedTerminal", 18 | "cwd": "${workspaceFolder}/packages/backend", 19 | "outFiles": [ 20 | "${workspaceFolder}/packages/backend/dist/**/*.js" 21 | ], 22 | "internalConsoleOptions": "openOnSessionStart" 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /packages/frontend/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import react from '@vitejs/plugin-react'; 3 | import path from 'path'; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [react()], 8 | server: { 9 | port: 3000, 10 | proxy: { 11 | '/api': { 12 | target: 'http://localhost:4000', 13 | changeOrigin: true, 14 | }, 15 | }, 16 | }, 17 | resolve: { 18 | alias: { 19 | '@workflow-automation/common': '../common/src', 20 | '@': path.resolve(__dirname, './src'), 21 | }, 22 | }, 23 | optimizeDeps: { 24 | include: ['tailwindcss', 'postcss'], 25 | }, 26 | build: { 27 | commonjsOptions: { 28 | include: [/\.cjs/], 29 | }, 30 | }, 31 | }); 32 | -------------------------------------------------------------------------------- /packages/frontend/src/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "../../lib/utils" 4 | 5 | const Textarea = React.forwardRef< 6 | HTMLTextAreaElement, 7 | React.ComponentProps<"textarea"> 8 | >(({ className, ...props }, ref) => { 9 | return ( 10 |