Skip to content

Commit cfa9a23

Browse files
committed
refactor: remove ensure-compiled endpoint and related code from control plane (#476)
# Remove Flow Compilation Verification Endpoint This PR removes the `/flows/:slug/ensure-compiled` endpoint and its associated functionality from the Edge Worker control plane. The endpoint was designed to verify flow compilation against database records, but is no longer needed in the current architecture. Changes include: - Removed the `/flows/:slug/ensure-compiled` endpoint handler - Removed related interfaces: `EnsureCompiledResponse`, `EnsureCompiledRequest`, `ControlPlaneOptions`, and `SqlFunction` - Simplified the `createControlPlaneHandler` function by removing the optional configuration parameter - Removed authentication verification logic that was only used by this endpoint - Removed all tests related to the endpoint and its functionality This change streamlines the control plane API to focus on its core functionality of serving compiled flows.
1 parent b0f0a33 commit cfa9a23

File tree

2 files changed

+4
-552
lines changed

2 files changed

+4
-552
lines changed
Lines changed: 2 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import type { AnyFlow, FlowShape } from '@pgflow/dsl';
1+
import type { AnyFlow } from '@pgflow/dsl';
22
import { compileFlow } from '@pgflow/dsl';
3-
import { isLocalSupabase } from '../shared/localDetection.ts';
43

54
/**
65
* Response type for the /flows/:slug endpoint
@@ -18,38 +17,6 @@ export interface ErrorResponse {
1817
message: string;
1918
}
2019

21-
/**
22-
* Response type for the /flows/:slug/ensure-compiled endpoint
23-
*/
24-
export interface EnsureCompiledResponse {
25-
status: 'compiled' | 'verified' | 'recompiled' | 'mismatch';
26-
differences: string[];
27-
mode: 'development' | 'production';
28-
}
29-
30-
/**
31-
* Request body for the /flows/:slug/ensure-compiled endpoint
32-
*/
33-
export interface EnsureCompiledRequest {
34-
shape: FlowShape;
35-
}
36-
37-
/**
38-
* SQL function interface for database operations
39-
* Compatible with the postgres library's tagged template interface
40-
*/
41-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
42-
// deno-lint-ignore no-explicit-any
43-
export type SqlFunction = (strings: TemplateStringsArray, ...values: any[]) => Promise<any[]>;
44-
45-
/**
46-
* Options for configuring the ControlPlane handler
47-
*/
48-
export interface ControlPlaneOptions {
49-
/** SQL function for database operations (required for ensure-compiled endpoint) */
50-
sql?: SqlFunction;
51-
}
52-
5320
/**
5421
* Input type for flow registration - accepts array or object (for namespace imports)
5522
*/
@@ -87,13 +54,9 @@ function buildFlowRegistry(flows: AnyFlow[]): Map<string, AnyFlow> {
8754
/**
8855
* Creates a request handler for the ControlPlane HTTP API
8956
* @param flowsInput Array or object of flow definitions to register
90-
* @param options Optional configuration for database and authentication
9157
* @returns Request handler function
9258
*/
93-
export function createControlPlaneHandler(
94-
flowsInput: FlowInput,
95-
options?: ControlPlaneOptions
96-
) {
59+
export function createControlPlaneHandler(flowsInput: FlowInput) {
9760
const flows = normalizeFlowInput(flowsInput);
9861
const registry = buildFlowRegistry(flows);
9962

@@ -112,15 +75,6 @@ export function createControlPlaneHandler(
11275
return handleGetFlow(registry, slug);
11376
}
11477

115-
// Handle POST /flows/:slug/ensure-compiled
116-
const ensureCompiledMatch = pathname.match(
117-
/^\/flows\/([a-zA-Z0-9_]+)\/ensure-compiled$/
118-
);
119-
if (ensureCompiledMatch && req.method === 'POST') {
120-
const slug = ensureCompiledMatch[1];
121-
return handleEnsureCompiled(req, slug, options);
122-
}
123-
12478
// 404 for unknown routes
12579
return jsonResponse(
12680
{
@@ -192,121 +146,3 @@ function jsonResponse(data: unknown, status: number): Response {
192146
},
193147
});
194148
}
195-
196-
/**
197-
* Verifies authentication using apikey header against SUPABASE_SERVICE_ROLE_KEY env var
198-
*/
199-
function verifyAuth(request: Request): boolean {
200-
const serviceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY');
201-
if (!serviceRoleKey) return false;
202-
const apikey = request.headers.get('apikey');
203-
return apikey === serviceRoleKey;
204-
}
205-
206-
/**
207-
* Validates the ensure-compiled request body
208-
*/
209-
function validateEnsureCompiledBody(
210-
body: unknown
211-
): { valid: true; data: EnsureCompiledRequest } | { valid: false; error: string } {
212-
if (!body || typeof body !== 'object') {
213-
return { valid: false, error: 'Request body must be an object' };
214-
}
215-
216-
const { shape } = body as Record<string, unknown>;
217-
218-
if (!shape || typeof shape !== 'object') {
219-
return { valid: false, error: 'Missing or invalid shape in request body' };
220-
}
221-
222-
return { valid: true, data: { shape: shape as FlowShape } };
223-
}
224-
225-
/**
226-
* Handles POST /flows/:slug/ensure-compiled requests
227-
*/
228-
async function handleEnsureCompiled(
229-
request: Request,
230-
flowSlug: string,
231-
options?: ControlPlaneOptions
232-
): Promise<Response> {
233-
// Check if SQL is configured
234-
if (!options?.sql) {
235-
return jsonResponse(
236-
{
237-
error: 'Not Found',
238-
message: 'ensure-compiled endpoint requires SQL configuration',
239-
},
240-
404
241-
);
242-
}
243-
244-
// Verify authentication
245-
if (!verifyAuth(request)) {
246-
return jsonResponse(
247-
{
248-
error: 'Unauthorized',
249-
message: 'Invalid or missing apikey header',
250-
},
251-
401
252-
);
253-
}
254-
255-
// Parse and validate request body
256-
let body: unknown;
257-
try {
258-
body = await request.json();
259-
} catch {
260-
return jsonResponse(
261-
{
262-
error: 'Bad Request',
263-
message: 'Invalid JSON in request body',
264-
},
265-
400
266-
);
267-
}
268-
269-
const validation = validateEnsureCompiledBody(body);
270-
if (!validation.valid) {
271-
return jsonResponse(
272-
{
273-
error: 'Bad Request',
274-
message: validation.error,
275-
},
276-
400
277-
);
278-
}
279-
280-
const { shape } = validation.data;
281-
282-
// Auto-detect mode based on environment
283-
const mode = isLocalSupabase() ? 'development' : 'production';
284-
285-
// Call SQL function
286-
try {
287-
const [result] = await options.sql`
288-
SELECT pgflow.ensure_flow_compiled(
289-
${flowSlug},
290-
${JSON.stringify(shape)}::jsonb,
291-
${mode}
292-
) as result
293-
`;
294-
295-
// Include detected mode in response for transparency
296-
const response: EnsureCompiledResponse = {
297-
...result.result,
298-
mode,
299-
};
300-
301-
return jsonResponse(response, response.status === 'mismatch' ? 409 : 200);
302-
} catch (error) {
303-
console.error('Error calling ensure_flow_compiled:', error);
304-
return jsonResponse(
305-
{
306-
error: 'Database Error',
307-
message: error instanceof Error ? error.message : 'Unknown error',
308-
},
309-
500
310-
);
311-
}
312-
}

0 commit comments

Comments
 (0)