Skip to content

Commit 9bdec19

Browse files
committed
Automation initial commit
1 parent 27b3fbe commit 9bdec19

71 files changed

Lines changed: 30988 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/server/null/STANDUP.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2026-03-01T20:55:55.690Z
2+
3+
[object Object]
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Shared utilities for automation routes
3+
*/
4+
5+
import type { Request, Response } from 'express';
6+
import type { AutomationScope } from '@automaker/types';
7+
8+
function asNonEmptyString(value: unknown): string | undefined {
9+
if (typeof value !== 'string') return undefined;
10+
const trimmed = value.trim();
11+
return trimmed.length > 0 ? trimmed : undefined;
12+
}
13+
14+
/**
15+
* Extract project path from request query or body
16+
*/
17+
export function getProjectPath(req: Request): string | undefined {
18+
return asNonEmptyString(req.query.projectPath) ?? asNonEmptyString(req.body?.projectPath);
19+
}
20+
21+
/**
22+
* Extract scope from request query or body
23+
*/
24+
export function getScope(req: Request): AutomationScope | undefined {
25+
const scope =
26+
(asNonEmptyString(req.query.scope) as AutomationScope | undefined) ??
27+
(asNonEmptyString(req.body?.scope) as AutomationScope | undefined);
28+
29+
if (scope === 'global' || scope === 'project') {
30+
return scope;
31+
}
32+
33+
return undefined;
34+
}
35+
36+
/**
37+
* Normalize route error responses.
38+
*
39+
* Errors whose message contains "already exists" are mapped to 409 Conflict.
40+
* All other unhandled errors use 500 Internal Server Error.
41+
*/
42+
export function sendRouteError(res: Response, error: unknown): void {
43+
const message = error instanceof Error ? error.message : String(error);
44+
const status = /already exists/i.test(message) ? 409 : 500;
45+
res.status(status).json({ success: false, error: message });
46+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/**
2+
* Automation Routes - API endpoints for automation management
3+
*
4+
* Routes:
5+
* - GET /api/automation/list - List automations (with scope/projectPath filter)
6+
* - POST /api/automation - Create a new automation
7+
* - GET /api/automation/:automationId - Get automation by ID
8+
* - PUT /api/automation/:automationId - Update an automation
9+
* - PATCH /api/automation/:automationId/enabled - Toggle enabled state
10+
* - DELETE /api/automation/:automationId - Delete an automation
11+
* - POST /api/automation/:automationId/duplicate - Duplicate an automation
12+
* - POST /api/automation/:automationId/trigger - Manually trigger automation
13+
* - * /api/automation/webhook/:automationId - Webhook trigger endpoint
14+
* - POST /api/automation/import - Import automation from JSON
15+
* - GET /api/automation/export - Export multiple automations as JSON
16+
* - GET /api/automation/:automationId/export - Export a single automation as JSON
17+
* - GET /api/automation/scheduled - List scheduled runs
18+
* - GET /api/automation/scheduled/upcoming - Get upcoming scheduled runs
19+
* - GET /api/automation/scheduled/:scheduledRunId - Get specific scheduled run
20+
* - DELETE /api/automation/scheduled/:scheduledRunId - Cancel a scheduled run
21+
* - GET /api/automation/runs - List automation runs
22+
* - GET /api/automation/runs/:runId - Get specific run
23+
* - GET /api/automation/variables - List available variables
24+
* - GET /api/automation/variables/system - Get system variables
25+
* - GET /api/automation/variables/project - Get project variables
26+
* - POST /api/automation/variables/project - Set project variable
27+
* - DELETE /api/automation/variables/project/:name - Delete project variable
28+
*/
29+
30+
import { Router } from 'express';
31+
import type { AutomationSchedulerService } from '../../services/automation-scheduler-service.js';
32+
import type { AutomationRuntimeEngine } from '../../services/automation-runtime-engine.js';
33+
import type { AutomationVariableService } from '../../services/automation-variable-service.js';
34+
import { createListRoute } from './routes/list.js';
35+
import { createGetRoute } from './routes/get.js';
36+
import { createManageRoute } from './routes/manage.js';
37+
import { createTriggerRoute } from './routes/trigger.js';
38+
import { createWebhookRoute } from './routes/webhook.js';
39+
import { createScheduleRoute } from './routes/schedule.js';
40+
import { createRunsRoute } from './routes/runs.js';
41+
import { createVariablesRoute } from './routes/variables.js';
42+
import { createGenerateRoute } from './routes/generate.js';
43+
44+
export function createAutomationRoutes(
45+
scheduler: AutomationSchedulerService,
46+
engine: AutomationRuntimeEngine,
47+
variableService: AutomationVariableService
48+
): Router {
49+
const router = Router();
50+
51+
const store = engine.getDefinitionStore();
52+
53+
// Mount routes - order matters for path matching
54+
55+
// AI generation routes (must come before /:automationId routes)
56+
router.use('/', createGenerateRoute());
57+
58+
// Webhook routes first (most specific paths with fixed 'webhook' prefix)
59+
router.use('/', createWebhookRoute(scheduler));
60+
61+
// Scheduled runs management
62+
// Must come before /:automationId routes to avoid 'scheduled' being treated as an ID
63+
router.use('/', createScheduleRoute(scheduler));
64+
65+
// Runs management
66+
// Must come before /:automationId routes to avoid 'runs' being treated as an ID
67+
router.use('/', createRunsRoute(engine));
68+
69+
// Variable management
70+
// Must come before /:automationId routes to avoid 'variables' being treated as an ID
71+
router.use('/', createVariablesRoute(variableService));
72+
73+
// Automation management: create, update, enable/disable, delete, import, export, duplicate
74+
// /export and /import must come before /:automationId routes
75+
router.use('/', createManageRoute(store, scheduler));
76+
77+
// List automations (GET /list)
78+
router.use('/', createListRoute(store));
79+
80+
// Trigger automation manually (POST /:automationId/trigger)
81+
// Must come before generic /:automationId route
82+
router.use('/', createTriggerRoute(scheduler));
83+
84+
// Get automation by ID (GET /:automationId)
85+
// Must be last among routes using /:automationId pattern
86+
router.use('/', createGetRoute(store));
87+
88+
return router;
89+
}

0 commit comments

Comments
 (0)