1+ import { NextRequest , NextResponse } from 'next/server'
2+ import { eq } from 'drizzle-orm'
3+ import { z } from 'zod'
4+ import { getSession } from '@/lib/auth'
5+ import { createLogger } from '@/lib/logs/console-logger'
6+ import { db } from '@/db'
7+ import { workflow } from '@/db/schema'
8+ import { Variable } from '@/stores/panel/variables/types'
9+
10+ const logger = createLogger ( 'WorkflowVariablesAPI' )
11+
12+ // Schema for workflow variables updates
13+ const VariablesSchema = z . object ( {
14+ variables : z . array (
15+ z . object ( {
16+ id : z . string ( ) ,
17+ workflowId : z . string ( ) ,
18+ name : z . string ( ) ,
19+ type : z . enum ( [ 'string' , 'number' , 'boolean' , 'object' , 'array' ] ) ,
20+ value : z . union ( [ z . string ( ) , z . number ( ) , z . boolean ( ) , z . record ( z . any ( ) ) , z . array ( z . any ( ) ) ] ) ,
21+ } )
22+ ) ,
23+ } )
24+
25+ export async function POST (
26+ req : NextRequest ,
27+ { params } : { params : Promise < { id : string } > }
28+ ) {
29+ const requestId = crypto . randomUUID ( ) . slice ( 0 , 8 )
30+ const workflowId = ( await params ) . id
31+
32+ try {
33+ const session = await getSession ( )
34+ if ( ! session ?. user ?. id ) {
35+ logger . warn ( `[${ requestId } ] Unauthorized workflow variables update attempt` )
36+ return NextResponse . json ( { error : 'Unauthorized' } , { status : 401 } )
37+ }
38+
39+ // Check if the workflow belongs to the user
40+ const workflowRecord = await db
41+ . select ( )
42+ . from ( workflow )
43+ . where ( eq ( workflow . id , workflowId ) )
44+ . limit ( 1 )
45+
46+ if ( ! workflowRecord . length ) {
47+ logger . warn ( `[${ requestId } ] Workflow not found: ${ workflowId } ` )
48+ return NextResponse . json ( { error : 'Workflow not found' } , { status : 404 } )
49+ }
50+
51+ if ( workflowRecord [ 0 ] . userId !== session . user . id ) {
52+ logger . warn (
53+ `[${ requestId } ] User ${ session . user . id } attempted to update variables for workflow ${ workflowId } owned by ${ workflowRecord [ 0 ] . userId } `
54+ )
55+ return NextResponse . json ( { error : 'Unauthorized' } , { status : 401 } )
56+ }
57+
58+ const body = await req . json ( )
59+
60+ try {
61+ const { variables } = VariablesSchema . parse ( body )
62+
63+ // Format variables for storage
64+ const variablesRecord : Record < string , Variable > = { }
65+ variables . forEach ( ( variable ) => {
66+ variablesRecord [ variable . id ] = variable
67+ } )
68+
69+ // Update workflow with variables
70+ await db
71+ . update ( workflow )
72+ . set ( {
73+ variables : variablesRecord ,
74+ updatedAt : new Date ( ) ,
75+ } )
76+ . where ( eq ( workflow . id , workflowId ) )
77+
78+ return NextResponse . json ( { success : true } )
79+ } catch ( validationError ) {
80+ if ( validationError instanceof z . ZodError ) {
81+ logger . warn ( `[${ requestId } ] Invalid workflow variables data` , {
82+ errors : validationError . errors ,
83+ } )
84+ return NextResponse . json (
85+ { error : 'Invalid request data' , details : validationError . errors } ,
86+ { status : 400 }
87+ )
88+ }
89+ throw validationError
90+ }
91+ } catch ( error ) {
92+ logger . error ( `[${ requestId } ] Error updating workflow variables` , error )
93+ return NextResponse . json (
94+ { error : 'Failed to update workflow variables' } ,
95+ { status : 500 }
96+ )
97+ }
98+ }
99+
100+ export async function GET (
101+ req : NextRequest ,
102+ { params } : { params : Promise < { id : string } > }
103+ ) {
104+ const requestId = crypto . randomUUID ( ) . slice ( 0 , 8 )
105+ const workflowId = ( await params ) . id
106+
107+ try {
108+ // Get the session directly in the API route
109+ const session = await getSession ( )
110+ if ( ! session ?. user ?. id ) {
111+ logger . warn ( `[${ requestId } ] Unauthorized workflow variables access attempt` )
112+ return NextResponse . json ( { error : 'Unauthorized' } , { status : 401 } )
113+ }
114+
115+ // Check if the workflow belongs to the user
116+ const workflowRecord = await db
117+ . select ( )
118+ . from ( workflow )
119+ . where ( eq ( workflow . id , workflowId ) )
120+ . limit ( 1 )
121+
122+ if ( ! workflowRecord . length ) {
123+ logger . warn ( `[${ requestId } ] Workflow not found: ${ workflowId } ` )
124+ return NextResponse . json ( { error : 'Workflow not found' } , { status : 404 } )
125+ }
126+
127+ if ( workflowRecord [ 0 ] . userId !== session . user . id ) {
128+ logger . warn (
129+ `[${ requestId } ] User ${ session . user . id } attempted to access variables for workflow ${ workflowId } owned by ${ workflowRecord [ 0 ] . userId } `
130+ )
131+ return NextResponse . json ( { error : 'Unauthorized' } , { status : 401 } )
132+ }
133+
134+ // Return variables if they exist
135+ const variables = workflowRecord [ 0 ] . variables as Record < string , Variable > || { }
136+
137+ // Add cache headers to prevent frequent reloading
138+ const headers = new Headers ( {
139+ 'Cache-Control' : 'max-age=60, stale-while-revalidate=300' , // Cache for 1 minute, stale for 5
140+ 'ETag' : `"${ requestId } -${ Object . keys ( variables ) . length } "` ,
141+ } )
142+
143+ return NextResponse . json ( { data : variables } , {
144+ status : 200 ,
145+ headers,
146+ } )
147+ } catch ( error : any ) {
148+ logger . error ( `[${ requestId } ] Workflow variables fetch error` , error )
149+ return NextResponse . json ( { error : error . message } , { status : 500 } )
150+ }
151+ }
0 commit comments