File size: 3,121 Bytes
5816640
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import type { Router } from 'express';
import { supabase, tableMissing } from '../supabase.js';

const FLOW_EXECUTOR = process.env.SUPABASE_FLOW_EXECUTOR || 'flow-executor';

export function registerFlowRoutes(router: Router) {
  router.get('/flows', async (req, res, next) => {
    const { status, type } = req.query;
    try {
      let query = supabase.from('flows').select('*').order('created_at', { ascending: false });

      if (status && typeof status === 'string') {
        query = query.eq('status', status);
      }

      if (type && typeof type === 'string') {
        query = query.eq('type', type);
      }

      const { data, error } = await query;
      if (error && !tableMissing(error)) throw error;

      res.json({ flows: data ?? [] });
    } catch (error) {
      next(error);
    }
  });

  router.post('/flows/:id/execute', async (req, res, next) => {
    const { id } = req.params;
    try {
      const { data, error } = await supabase.functions.invoke(FLOW_EXECUTOR, {
        body: { flowId: id, parameters: req.body?.parameters ?? {} },
      });

      if (error) {
        // bubble up but mark accepted so caller can inspect details
        return res.status(502).json({ success: false, error: error.message });
      }

      res.status(202).json({ success: true, response: data });
    } catch (error) {
      next(error);
    }
  });

  router.post('/flows/:id/publish', async (req, res, next) => {
    const { id } = req.params;
    try {
      const { data, error } = await supabase
        .from('flows')
        .update({ status: 'live', published_at: new Date().toISOString() })
        .eq('id', id)
        .select()
        .single();

      if (error) throw error;

      res.json({ success: true, flow: data });
    } catch (error) {
      next(error);
    }
  });

  router.post('/flows/:id/duplicate', async (req, res, next) => {
    const { id } = req.params;
    try {
      const { data: original, error: fetchError } = await supabase
        .from('flows')
        .select('*')
        .eq('id', id)
        .single();

      if (fetchError) throw fetchError;

      const payload = {
        ...original,
        id: undefined,
        name: `${original.name} Copy`,
        status: 'draft',
        created_at: undefined,
        updated_at: undefined,
        published_at: null,
        last_run_at: null,
      };

      const { data: inserted, error: insertError } = await supabase
        .from('flows')
        .insert(payload)
        .select()
        .single();

      if (insertError) throw insertError;

      res.json({ success: true, flow: inserted });
    } catch (error) {
      next(error);
    }
  });

  router.post('/flows/:id/archive', async (req, res, next) => {
    const { id } = req.params;
    try {
      const { data, error } = await supabase
        .from('flows')
        .update({ status: 'archived', archived_at: new Date().toISOString() })
        .eq('id', id)
        .select()
        .single();

      if (error) throw error;

      res.json({ success: true, flow: data });
    } catch (error) {
      next(error);
    }
  });
}