├── README.md ├── LICENSE.md ├── pnpm-workspace.yaml ├── .gitignore ├── examples └── nextjs-blog-cms │ ├── supabase │ ├── .gitignore │ ├── schema.sql │ └── config.toml │ ├── .eslintrc.json │ ├── app │ ├── favicon.ico │ ├── fonts │ │ ├── GeistVF.woff │ │ └── GeistMonoVF.woff │ ├── page.tsx │ ├── automation │ │ ├── page.tsx │ │ └── [id] │ │ │ └── page.tsx │ ├── api │ │ ├── inngest │ │ │ └── route.ts │ │ ├── workflows │ │ │ └── route.ts │ │ └── blog-posts │ │ │ └── route.ts │ ├── layout.tsx │ ├── actions.ts │ ├── globals.css │ └── blog-post │ │ └── [id] │ │ └── page.tsx │ ├── next.config.mjs │ ├── workflow-editor.png │ ├── lib │ ├── inngest │ │ ├── client.ts │ │ ├── workflow.ts │ │ └── workflowActions.ts │ ├── supabase │ │ ├── client.ts │ │ ├── types.ts │ │ ├── server.ts │ │ └── database.types.ts │ ├── loaders │ │ ├── workflow.ts │ │ └── blog-post.ts │ ├── utils.ts │ └── mdxComponents.tsx │ ├── postcss.config.mjs │ ├── .env.example │ ├── components.json │ ├── .gitignore │ ├── tsconfig.json │ ├── components │ ├── ui │ │ ├── label.tsx │ │ ├── checkbox.tsx │ │ ├── badge.tsx │ │ ├── switch.tsx │ │ ├── button.tsx │ │ ├── tabs.tsx │ │ ├── card.tsx │ │ └── select.tsx │ ├── menu.tsx │ ├── blog-post-actions.tsx │ ├── automation-editor.tsx │ ├── automation-list.tsx │ └── blog-post-list.tsx │ ├── package.json │ ├── tailwind.config.ts │ ├── README.md │ └── LICENSE.md ├── packages └── workflow │ ├── src │ ├── stories │ │ ├── ui.storybook.css │ │ ├── UI.stories.jsx │ │ └── UI.jsx │ ├── ui │ │ ├── sidebar │ │ │ ├── Footer.tsx │ │ │ ├── WorfklowForm.tsx │ │ │ ├── ActionList.tsx │ │ │ ├── Header.tsx │ │ │ ├── Sidebar.tsx │ │ │ └── ActionForm.tsx │ │ ├── Sidebar.tsx │ │ ├── nodes.tsx │ │ ├── index.ts │ │ ├── nodes │ │ │ ├── Trigger.tsx │ │ │ ├── Action.tsx │ │ │ └── Handles.tsx │ │ ├── layout.tsx │ │ ├── Provider.tsx │ │ ├── ui.css │ │ └── Editor.tsx │ ├── index.ts │ ├── builtin.ts │ ├── builtin.test.ts │ ├── graph.ts │ ├── engine.execution.test.ts │ ├── engine.test.ts │ ├── graph.test.ts │ ├── interpolation.ts │ ├── types.ts │ └── engine.ts │ ├── jest.config.js │ ├── CHANGELOG.md │ ├── .storybook │ ├── preview.js │ └── main.js │ ├── .gitignore │ ├── tsconfig.json │ ├── README.md │ └── package.json ├── .changeset ├── orange-coins-speak.md ├── odd-goats-dance.md ├── healthy-shoes-hear.md ├── quiet-buttons-yawn.md ├── dull-chairs-attend.md ├── config.json └── README.md ├── .github ├── assets │ ├── workflow-kit.jpg │ └── workflow-demo.gif └── workflows │ ├── release.yml │ └── pr.yml ├── package.json └── CONTRIBUTING.md /README.md: -------------------------------------------------------------------------------- 1 | ./packages/workflow/README.md -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ./packages/workflow/LICENSE.md -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "packages/*" 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Node packages 2 | node_modules 3 | 4 | # Nix 5 | /.direnv/ 6 | 7 | .env.local -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/supabase/.gitignore: -------------------------------------------------------------------------------- 1 | # Supabase 2 | .branches 3 | .temp 4 | .env 5 | -------------------------------------------------------------------------------- /packages/workflow/src/stories/ui.storybook.css: -------------------------------------------------------------------------------- 1 | .sb-wrap { 2 | height: 100vh; 3 | width: 100%; 4 | } -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next/core-web-vitals", "next/typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /.changeset/orange-coins-speak.md: -------------------------------------------------------------------------------- 1 | --- 2 | "@inngest/workflow-kit": minor 3 | --- 4 | 5 | Show edge names in editor 6 | -------------------------------------------------------------------------------- /.github/assets/workflow-kit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inngest/workflow-kit/HEAD/.github/assets/workflow-kit.jpg -------------------------------------------------------------------------------- /.github/assets/workflow-demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inngest/workflow-kit/HEAD/.github/assets/workflow-demo.gif -------------------------------------------------------------------------------- /.changeset/odd-goats-dance.md: -------------------------------------------------------------------------------- 1 | --- 2 | "@inngest/workflow-kit": minor 3 | --- 4 | 5 | Switch to a maintained version of jsonpath 6 | -------------------------------------------------------------------------------- /.changeset/healthy-shoes-hear.md: -------------------------------------------------------------------------------- 1 | --- 2 | "@inngest/workflow-kit": patch 3 | --- 4 | 5 | Minor improvements to conditional support 6 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inngest/workflow-kit/HEAD/examples/nextjs-blog-cms/app/favicon.ico -------------------------------------------------------------------------------- /.changeset/quiet-buttons-yawn.md: -------------------------------------------------------------------------------- 1 | --- 2 | "@inngest/workflow-kit": patch 3 | --- 4 | 5 | Fix to ensure nodes in a workflow are only run once 6 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | export default nextConfig; 5 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/workflow-editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inngest/workflow-kit/HEAD/examples/nextjs-blog-cms/workflow-editor.png -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/app/fonts/GeistVF.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inngest/workflow-kit/HEAD/examples/nextjs-blog-cms/app/fonts/GeistVF.woff -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/app/fonts/GeistMonoVF.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inngest/workflow-kit/HEAD/examples/nextjs-blog-cms/app/fonts/GeistMonoVF.woff -------------------------------------------------------------------------------- /.changeset/dull-chairs-attend.md: -------------------------------------------------------------------------------- 1 | --- 2 | "@inngest/workflow-kit": minor 3 | --- 4 | 5 | Execute Provider.onChange callback when action input values change 6 | -------------------------------------------------------------------------------- /packages/workflow/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest').JestConfigWithTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | }; -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/lib/inngest/client.ts: -------------------------------------------------------------------------------- 1 | import { Inngest } from "inngest"; 2 | 3 | export const inngest = new Inngest({ 4 | id: "workflow-kit-next-demo", 5 | }); 6 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/app/page.tsx: -------------------------------------------------------------------------------- 1 | import { BlogPostList } from "@/components/blog-post-list"; 2 | 3 | export default async function Dashboard() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /packages/workflow/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @inngest/workflow-kit 2 | 3 | ## 0.1.3 4 | 5 | ### Patch Changes 6 | 7 | - a40a1b6: feat(core): typing fixes 8 | - 04c146f: fix: do not update state in render 9 | -------------------------------------------------------------------------------- /packages/workflow/src/ui/sidebar/Footer.tsx: -------------------------------------------------------------------------------- 1 | export const SidebarFooter = () => { 2 | return ( 3 |
4 | {/* TODO: Add stuff */} 5 |
6 | ) 7 | } -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/app/automation/page.tsx: -------------------------------------------------------------------------------- 1 | import { AutomationList } from "@/components/automation-list"; 2 | 3 | export default async function Dashboard() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /packages/workflow/src/ui/Sidebar.tsx: -------------------------------------------------------------------------------- 1 | export * from "./sidebar/ActionForm"; 2 | export * from "./sidebar/ActionList"; 3 | export * from "./sidebar/Footer"; 4 | export * from "./sidebar/WorfklowForm"; 5 | export * from "./sidebar/Sidebar"; 6 | -------------------------------------------------------------------------------- /packages/workflow/src/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | type RunArgs, 3 | type EngineOptions, 4 | type EngineAction, 5 | type PublicEngineAction, 6 | type WorkflowAction, 7 | type WorkflowEdge, 8 | type Loader, 9 | type Workflow, 10 | } from "./types"; 11 | 12 | export { Engine } from "./engine"; 13 | -------------------------------------------------------------------------------- /packages/workflow/.storybook/preview.js: -------------------------------------------------------------------------------- 1 | /** @type { import('@storybook/react').Preview } */ 2 | const preview = { 3 | parameters: { 4 | controls: { 5 | matchers: { 6 | color: /(background|color)$/i, 7 | date: /Date$/i, 8 | }, 9 | }, 10 | }, 11 | }; 12 | 13 | export default preview; 14 | -------------------------------------------------------------------------------- /packages/workflow/.gitignore: -------------------------------------------------------------------------------- 1 | # Built files 2 | dist 3 | 4 | # Generated version file; always created pre-publish 5 | src/version.ts 6 | 7 | # Release-only files; tree must be clean on release, so these can't be modified 8 | .npmrc 9 | 10 | # Local dev files 11 | coverage/ 12 | 13 | tsdoc-metadata.json 14 | 15 | *storybook.log -------------------------------------------------------------------------------- /packages/workflow/src/ui/nodes.tsx: -------------------------------------------------------------------------------- 1 | export { 2 | ActionNode, 3 | BlankNode, 4 | type ActionNodeProps, 5 | } from "./nodes/Action"; 6 | 7 | export { 8 | TriggerNode, 9 | type TriggerNodeProps, 10 | } from "./nodes/Trigger"; 11 | 12 | export { 13 | NewBlankNode, 14 | type BlankNodeType, 15 | } from "./nodes/Handles"; -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/lib/supabase/client.ts: -------------------------------------------------------------------------------- 1 | import { createBrowserClient } from "@supabase/ssr"; 2 | import { Database } from "./types"; 3 | 4 | export function createClient() { 5 | return createBrowserClient( 6 | process.env.NEXT_PUBLIC_SUPABASE_URL!, 7 | process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! 8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/app/api/inngest/route.ts: -------------------------------------------------------------------------------- 1 | import { inngest } from "@/lib/inngest/client"; 2 | import workflow from "@/lib/inngest/workflow"; 3 | import { serve } from "inngest/next"; 4 | 5 | export const runtime = "edge"; 6 | 7 | export const { GET, POST, PUT } = serve({ 8 | client: inngest, 9 | functions: [workflow], 10 | }); 11 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/.env.example: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_SUPABASE_URL= 2 | NEXT_PUBLIC_SUPABASE_ANON_KEY= 3 | INNGEST_EVENT_KEY= 4 | INNGEST_SIGNING_KEY= 5 | OPENAI_API_KEY= 6 | OPENAI_MODEL=gpt-3.5-turbo -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "changeset": "changeset", 4 | "test": "pnpm run --if-present --recursive test", 5 | "build": "pnpm run --if-present --recursive build", 6 | "release": "pnpm run build && changeset publish" 7 | }, 8 | "dependencies": { 9 | "@changesets/cli": "^2.27.8", 10 | "@sinclair/typebox": "^0.33.7" 11 | }, 12 | "packageManager": "pnpm@9.4.0" 13 | } 14 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/app/api/workflows/route.ts: -------------------------------------------------------------------------------- 1 | import { createClient } from "@/lib/supabase/server"; 2 | import { NextResponse } from "next/server"; 3 | 4 | export async function GET() { 5 | const supabase = createClient(); 6 | const { data: workflows } = await supabase 7 | .from("workflows") 8 | .select("*") 9 | .order("id"); 10 | 11 | return NextResponse.json({ workflows }); 12 | } 13 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.3/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [], 11 | "snapshot": { 12 | "useCalculatedVersion": true, 13 | "prereleaseTemplate": "{tag}-{datetime}-{commit}" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/lib/loaders/workflow.ts: -------------------------------------------------------------------------------- 1 | import { Workflow } from "@inngest/workflow-kit"; 2 | 3 | import { createClient } from "../supabase/server"; 4 | 5 | export async function loadWorkflow(event: { name: string }) { 6 | const supabase = createClient(); 7 | const { data } = await supabase 8 | .from("workflows") 9 | .select("*", {}) 10 | .eq("trigger", event.name) 11 | .eq("enabled", true) 12 | .single(); 13 | return (data && data.workflow) as unknown as Workflow; 14 | } 15 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/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 | 8 | export function capitalize(str: string) { 9 | return str.charAt(0).toUpperCase() + str.slice(1); 10 | } 11 | 12 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 13 | export const fetcher = (...args: [any]) => 14 | fetch(...args).then((res) => res.json()); 15 | -------------------------------------------------------------------------------- /packages/workflow/src/ui/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | Editor, 3 | type Direction, 4 | type EditorProps, 5 | } from "./Editor"; 6 | export { 7 | Sidebar, 8 | type SidebarProps, 9 | } from "./Sidebar"; 10 | export { 11 | Provider, 12 | ProviderContext, 13 | useWorkflow, 14 | useTrigger, 15 | useAvailableActions, 16 | useOnChange, 17 | type ProviderProps, 18 | } from "./Provider"; 19 | export { 20 | TriggerNode, 21 | ActionNode, 22 | } from "./nodes"; 23 | 24 | // TODO: Trigger type -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "app/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | } 20 | } -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /packages/workflow/.storybook/main.js: -------------------------------------------------------------------------------- 1 | /** @type { import('@storybook/react-vite').StorybookConfig } */ 2 | const config = { 3 | stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], 4 | addons: [ 5 | "@storybook/addon-onboarding", 6 | "@storybook/addon-links", 7 | "@storybook/addon-essentials", 8 | "@chromatic-com/storybook", 9 | "@storybook/addon-interactions", 10 | ], 11 | framework: { 12 | name: "@storybook/react-vite", 13 | options: {}, 14 | }, 15 | }; 16 | export default config; 17 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/app/api/blog-posts/route.ts: -------------------------------------------------------------------------------- 1 | import { createClient } from "@/lib/supabase/server"; 2 | import { NextResponse } from "next/server"; 3 | 4 | export async function GET() { 5 | const supabase = createClient(); 6 | const { data: blogPosts } = await supabase 7 | .from("blog_posts") 8 | .select( 9 | "id, title, subtitle, markdown_ai_revision, created_at, status, markdown, ai_publishing_recommendations" 10 | ) 11 | .order("created_at", { ascending: false }); 12 | 13 | return NextResponse.json({ blogPosts }); 14 | } 15 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/app/automation/[id]/page.tsx: -------------------------------------------------------------------------------- 1 | import { AutomationEditor } from "@/components/automation-editor"; 2 | import { createClient } from "@/lib/supabase/server"; 3 | import { notFound } from "next/navigation"; 4 | 5 | export const runtime = "edge"; 6 | 7 | export default async function Automation({ 8 | params, 9 | }: { 10 | params: { id: string }; 11 | }) { 12 | const supabase = createClient(); 13 | const { data: workflow } = await supabase 14 | .from("workflows") 15 | .select("*") 16 | .eq("id", params.id!) 17 | .single(); 18 | if (workflow) { 19 | return ; 20 | } else { 21 | notFound(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/lib/loaders/blog-post.ts: -------------------------------------------------------------------------------- 1 | import { createClient } from "../supabase/server"; 2 | import { BlogPost } from "../supabase/types"; 3 | 4 | export async function loadBlogPost(id: string): Promise { 5 | const supabase = createClient(); 6 | const { data: blogPosts } = await supabase 7 | .from("blog_posts") 8 | .select( 9 | "id, title, subtitle, markdown_ai_revision, created_at, status, markdown, ai_publishing_recommendations" 10 | ) 11 | .eq("id", id) 12 | .limit(1); 13 | 14 | const blogPost = blogPosts && blogPosts[0]; 15 | 16 | if (!blogPost) { 17 | throw new Error(`Blog post #${id} not found`); 18 | } 19 | 20 | return blogPost; 21 | } 22 | -------------------------------------------------------------------------------- /packages/workflow/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "jsx": "react-jsx", 5 | "lib": ["ES2021", "DOM"], 6 | "module": "commonjs", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "sourceMap": true, 10 | "rootDir": "./src", 11 | "outDir": "./dist", 12 | "types": ["jest"], 13 | "moduleResolution": "node", 14 | "esModuleInterop": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "strict": true, 17 | "skipLibCheck": true, 18 | "noImplicitOverride": true, 19 | "resolveJsonModule": true, 20 | "noUncheckedIndexedAccess": true, 21 | "strictNullChecks": true 22 | }, 23 | "include": ["./src/**/*.ts"] 24 | } 25 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "noEmit": true, 9 | "incremental": true, 10 | "esModuleInterop": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Bundler", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "baseUrl": ".", 17 | "paths": { 18 | "@/*": ["./*"] 19 | }, 20 | "plugins": [ 21 | { 22 | "name": "next" 23 | } 24 | ], 25 | "strictNullChecks": true 26 | }, 27 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 28 | "exclude": ["node_modules"] 29 | } 30 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/lib/inngest/workflow.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from "@inngest/workflow-kit"; 2 | 3 | import { loadWorkflow } from "../loaders/workflow"; 4 | import { inngest } from "./client"; 5 | import { actionsWithHandlers } from "./workflowActionHandlers"; 6 | 7 | const workflowEngine = new Engine({ 8 | actions: actionsWithHandlers, 9 | loader: loadWorkflow, 10 | }); 11 | 12 | export default inngest.createFunction( 13 | { id: "blog-post-workflow" }, 14 | // Triggers 15 | // - When a blog post is set to "review" 16 | // - When a blog post is published 17 | [{ event: "blog-post.updated" }, { event: "blog-post.published" }], 18 | async ({ event, step }) => { 19 | // When `run` is called, the loader function is called with access to the event 20 | await workflowEngine.run({ event, step }); 21 | } 22 | ); 23 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as LabelPrimitive from "@radix-ui/react-label" 5 | import { cva, type VariantProps } from "class-variance-authority" 6 | 7 | import { cn } from "@/lib/utils" 8 | 9 | const labelVariants = cva( 10 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" 11 | ) 12 | 13 | const Label = React.forwardRef< 14 | React.ElementRef, 15 | React.ComponentPropsWithoutRef & 16 | VariantProps 17 | >(({ className, ...props }, ref) => ( 18 | 23 | )) 24 | Label.displayName = LabelPrimitive.Root.displayName 25 | 26 | export { Label } 27 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/lib/supabase/types.ts: -------------------------------------------------------------------------------- 1 | import { type Workflow as InngestWorkflow } from "@inngest/workflow-kit"; 2 | import { Database as SourceDatabase } from "./database.types"; 3 | 4 | // typing `workflows.workflow` Json field 5 | export type Database = { 6 | public: { 7 | Tables: Omit & { 8 | workflows: Omit< 9 | SourceDatabase["public"]["Tables"]["workflows"], 10 | "Row" 11 | > & { 12 | Row: Omit< 13 | SourceDatabase["public"]["Tables"]["workflows"]["Row"], 14 | "workflow" 15 | > & { 16 | workflow: InngestWorkflow; 17 | }; 18 | }; 19 | }; 20 | }; 21 | }; 22 | 23 | export type Workflow = Database["public"]["Tables"]["workflows"]["Row"]; 24 | export type BlogPost = Database["public"]["Tables"]["blog_posts"]["Row"]; 25 | -------------------------------------------------------------------------------- /examples/nextjs-blog-cms/lib/supabase/server.ts: -------------------------------------------------------------------------------- 1 | import { createServerClient } from "@supabase/ssr"; 2 | import { cookies } from "next/headers"; 3 | import { Database } from "./types"; 4 | 5 | export function createClient() { 6 | const cookieStore = cookies(); 7 | 8 | return createServerClient( 9 | process.env.NEXT_PUBLIC_SUPABASE_URL!, 10 | process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, 11 | { 12 | cookies: { 13 | getAll() { 14 | return cookieStore.getAll(); 15 | }, 16 | setAll(cookiesToSet) { 17 | try { 18 | cookiesToSet.forEach(({ name, value, options }) => 19 | cookieStore.set(name, value, options) 20 | ); 21 | } catch { 22 | // The `setAll` method was called from a Server Component. 23 | // This can be ignored if you have middleware refreshing 24 | // user sessions. 25 | } 26 | }, 27 | }, 28 | } 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /packages/workflow/src/ui/sidebar/WorfklowForm.tsx: -------------------------------------------------------------------------------- 1 | import { useProvider } from "../Provider"; 2 | 3 | /** 4 | * The form for editing a workflow's name and description. 5 | */ 6 | export const SidebarWorkflowForm = () => { 7 | const { workflow, onChange } = useProvider(); 8 | 9 | return ( 10 |
11 | 22 |