Skip to content

Commit 2bc4109

Browse files
krishna9358claude
andauthored
feat: Add Template Library (#278)
* feat: Add Template Library functionality - Add comprehensive template library for workflow templates - Support publishing workflows as templates with GitHub integration - Allow users to browse and use existing templates - Include template submission workflow with pull request generation - Add frontend UI for template discovery and usage - Add database schema for templates and submissions - Implement GitHub template service for fetching templates - Add workflow sanitization service to remove sensitive data - Include TypeScript type definitions and error handling Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * fix: Resolve ESLint/Prettier formatting issues in Template Library - Change Array<T> to T[] in templateStore.ts - Fix Select component props formatting in TemplateLibraryPage - Fix Button onClick callback formatting - Fix fetch call and .json() chaining formatting - Fix Publish as Template text wrapping in TopBar Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * fix: Resolve ESLint/Prettier formatting issues in backend templates - Change Array<T> to T[] throughout template files - Fix import statement formatting - Fix query chain formatting in repository - Fix unused variables by prefixing with underscore - Fix object literal formatting and error logging Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * fix: Temporarily disable Templates module due to Bun+NestJS compatibility issue The TemplatesModule causes a "function is not a constructor" error when loaded by NestJS in the Bun runtime. This is a known Bun+NestJS compatibility issue (see oven-sh/bun#4858). Changes: - Added forwardRef for WorkflowsModule import (good practice regardless) - Added comments documenting the temporary disable - Removed TemplatesModule from app.module.ts coreModules array The backend now starts successfully. The template library feature will be unavailable until this compatibility issue is resolved. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * feat: Refactor Template Library to use GitHub web flow This commit refactors the Template Library to use GitHub's web flow for publishing instead of Octokit API, and fixes Bun+NestJS compatibility issues. Changes: - Frontend now generates GitHub URLs directly for template submission - Added GitHub sync service to fetch templates from repository - Made template listing endpoints public for browsing - Fixed Bun+NestJS constructor error by removing duplicate providers - Replaced RequireWorkflowRole with RolesGuard to avoid module dependencies - Added better PR creation instructions in the publish modal - Removed Octokit dependency and token from backend Users can now: 1. Publish workflows as templates via GitHub PR flow 2. Browse templates from the library (after sync from GitHub) 3. Sync templates from GitHub repo to database via admin endpoint Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * feat: Add GitHub webhook endpoint for automatic template sync Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * feat: Add GITHUB_WEBHOOK_SECRET env var placeholder This is required for webhook signature verification. Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * fix: Remove dead syncTemplates method from TemplateService The sync is now handled directly by GitHubSyncService in the controller. This removes confusing dead code that returned a "disabled" message. Also fixes ESLint errors for unused parameters. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * feat: Simplify template sync to startup-only with rate limit handling - Remove webhook controller and token auth (repo is public) - Remove periodic sync interval to avoid GitHub rate limit exhaustion - Add graceful 403 rate limit handling in GitHub API calls - Fix findAll() query composition bug using and() pattern - Add tag filtering, ILIKE escaping, and proper sort ordering - Add ARCHITECTURE.md documenting the template library system Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * fix: Resolve lint and prettier formatting errors in frontend templates Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * fix: Use clipboard instead of URL for template content to avoid GitHub URL length limit Large workflow graphs were causing "URL is too long" errors on GitHub. Now copies template JSON to clipboard and instructs user to paste it in the GitHub editor. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * fix: Fix template sync validation and improve publish UX Backend: Remove mandatory `manifest` field check - actual templates only have `_metadata`, `graph`, and `requiredSecrets`. Build manifest from `_metadata` for DB storage. Frontend: Strip viewport/position data from graph to reduce URL size. Embed template content in GitHub URL when it fits (<7.5KB), fall back to clipboard with paste instructions only for very large templates. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * feat: Implement Use Template, fix publish UX, fix card layout - Implement useTemplate endpoint: creates a real workflow from template graph via WorkflowsService, increments popularity counter - Publish flow: use minified JSON + stripped layout data to always embed content in GitHub URL (no clipboard fallback) - Template cards: fix inconsistent button positioning with flex layout so buttons are always pinned to the bottom of each card Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * fix: Fix Use Template redirect, restore JSON formatting, add GitHub token support - Fix workflowId undefined in redirect by mapping backend response (workflow.id → workflowId) in templateStore - Restore pretty-printed JSON (2-space indent) in publish flow so GitHub renders syntax highlighting correctly - Add optional GITHUB_TEMPLATE_TOKEN env var for authenticated API requests (60 → 5000 req/hr) with startup log showing auth status Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * feat: Add ETag conditional requests and fix missing node positions - Implement ETag-based caching in GitHub sync service: stores ETags per URL, sends If-None-Match on subsequent requests, returns cached data on 304 Not Modified (zero rate limit cost) - Fix Use Template 500 error caused by missing node positions: add default grid layout positions for nodes that lack them before WorkflowGraphSchema validation - Stop stripping node positions during publish (required by schema), only strip viewport which has a schema default - Sync response now includes unchanged[] and directoryCacheHit stats Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * fix: use clipboard copy-paste for GitHub webflow to avoid long URL errors Template content is no longer embedded in the GitHub URL params, which caused browser URL length limit errors for large workflows. Instead, the code is auto-copied to clipboard and users paste it in the GitHub editor. A "Copy Template Code" button is shown in the success state for re-copying. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * fix(test): mock IsolatedContainerVolume in naabu tests Tests were failing because IsolatedContainerVolume tried to create real Docker volumes. Mock the volume class so tests don't require a running Docker daemon. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * fix: add explanatory note for GitHub PR workflow in publish modal Clarify that templates are submitted via GitHub pull requests and that users need to paste the copied code into the GitHub editor. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * feat: add GITHUB_TEMPLATE_* env vars to backend validation schema Add Zod validation for GITHUB_TEMPLATE_REPO (owner/repo format), GITHUB_TEMPLATE_BRANCH, and GITHUB_TEMPLATE_TOKEN to catch misconfiguration at startup instead of silent runtime failures. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * feat: add workflow preview thumbnails and revamp template library UI - Add inline SVG workflow graph previews on template cards - Cursor-based zoom with scroll wheel and transform-origin tracking - Category-themed gradients, icons, and color-coded badges - Improved card design with hover animations and better layout - Better loading skeletons, empty state, and error handling Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * fix: improve workflow preview thumbnails and UI polish - Card-style nodes with header band, icon, label, subtitle, port dots - Wider nodes (160px) matching real builder proportions - Stronger shadows and contrast for dark/light mode visibility - Add "scroll to zoom" hint on hover - Indent tag filter row for alignment - Better edge styling with thicker arrows Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * feat: improve template library UI, add JSONC support, and consolidate navbar actions - Template cards: display tags and author metadata side by side - JSONC support: publish templates as .jsonc, backend strips comments before parsing, sync accepts both .json and .jsonc files - GitHub publish flow: pre-fill editor with placeholder comment - Navbar: consolidate undo/redo/import/export into vertical three-dots menu to the right of the Run button Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * feat: redesign template cards with premium marketplace styling Implements detailed design spec with rounded-2xl cards, theme-specific preview gradients, author avatars, title case names, marketplace metadata (stars, secrets, updated time), full-width indigo CTA with arrow animation, eye preview button with tooltip, and tag overflow tooltip. Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * feat: add automatic GitHub template sync every 30 minutes Replaces manual-only sync with a recurring setInterval that syncs templates from GitHub every 30 minutes. ETag caching ensures minimal API cost when nothing has changed. Cleans up interval on module destroy. Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * fix: use primary color for CTA button and deduplicate category from tags Switch "Use Template" button from hardcoded indigo to the codebase's primary color token. Filter out the category name from the tags list so it doesn't appear redundantly in both the badge and tags row. Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * feat: add template detail modal and move page title to navbar Add click-to-preview modal on template cards showing large graph, full title/description, and Use Template CTA. Move page title to AppTopBar navbar and remove in-page header to match Schedules layout. Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * fix: address code review findings for template library - Sanitize {{secret:SECRET_ID}} references in publish validation (#1) - Migrate UseTemplateModal from Zustand to TanStack Query mutation (#2) - Reset modal state on template/open change to prevent stale data (#3) - Fetch GitHub repo config dynamically with fallback defaults (#4) - Use snake_case keys for analytics event properties (#5) Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> * fix: there were multiple bugs after reviewing like secret mapping ,env fixed them. Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> --------- Signed-off-by: Krishna Mohan <krishanmohank974@gmail.com> Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
1 parent 9213d5c commit 2bc4109

34 files changed

Lines changed: 5190 additions & 153 deletions

.github/workflows/release.yml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Release
33
on:
44
push:
55
tags:
6-
- 'v*.*.*' # Triggers on tags like v1.0.0, v1.2.3, etc.
6+
- 'v*.*.*' # Triggers on tags like v1.0.0, v1.2.3, etc.
77
workflow_dispatch:
88
inputs:
99
version:
@@ -27,7 +27,7 @@ jobs:
2727
- name: Checkout repository
2828
uses: actions/checkout@v4
2929
with:
30-
fetch-depth: 0 # Full history for changelog generation
30+
fetch-depth: 0 # Full history for changelog generation
3131

3232
- name: Set up QEMU
3333
uses: docker/setup-qemu-action@v3
@@ -62,7 +62,7 @@ jobs:
6262
# Check if this is the latest tag (highest semver)
6363
CURRENT_TAG="${{ steps.version.outputs.version_clean }}"
6464
LATEST_TAG=$(git tag -l 'v*.*.*' | sort -V | tail -1 | sed 's/^v//')
65-
65+
6666
if [ "$CURRENT_TAG" = "$LATEST_TAG" ]; then
6767
echo "is_latest=true" >> $GITHUB_OUTPUT
6868
echo "This is the latest release"
@@ -81,7 +81,7 @@ jobs:
8181
# Convert repository owner to lowercase for Docker registry compatibility
8282
IMAGE_PREFIX_LOWER=$(echo "${{ env.IMAGE_PREFIX }}" | tr '[:upper:]' '[:lower:]')
8383
VERSION_TAG="${{ env.REGISTRY }}/${IMAGE_PREFIX_LOWER}-backend:${{ steps.version.outputs.version_clean }}"
84-
84+
8585
if [ "${{ steps.is_latest.outputs.is_latest }}" = "true" ]; then
8686
echo "backend_tags<<EOF" >> $GITHUB_OUTPUT
8787
echo "$VERSION_TAG" >> $GITHUB_OUTPUT
@@ -166,22 +166,22 @@ jobs:
166166
run: |
167167
VERSION="${{ steps.version.outputs.version }}"
168168
PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
169-
169+
170170
# Convert repository owner to lowercase for Docker registry compatibility
171171
IMAGE_PREFIX_LOWER=$(echo "${{ env.IMAGE_PREFIX }}" | tr '[:upper:]' '[:lower:]')
172-
172+
173173
if [ -z "$PREVIOUS_TAG" ]; then
174174
echo "No previous tag found, generating full changelog"
175175
CHANGELOG=$(git log --pretty=format:"- %s (%h)" --no-merges)
176176
else
177177
echo "Generating changelog from $PREVIOUS_TAG to $VERSION"
178178
CHANGELOG=$(git log ${PREVIOUS_TAG}..HEAD --pretty=format:"- %s (%h)" --no-merges)
179179
fi
180-
180+
181181
if [ -z "$CHANGELOG" ]; then
182182
CHANGELOG="No changes detected"
183183
fi
184-
184+
185185
{
186186
echo "## Release $VERSION"
187187
echo ""
@@ -195,7 +195,7 @@ jobs:
195195
echo ""
196196
echo "$CHANGELOG"
197197
} > CHANGELOG.md
198-
198+
199199
echo "changelog<<EOF" >> $GITHUB_OUTPUT
200200
cat CHANGELOG.md >> $GITHUB_OUTPUT
201201
echo "EOF" >> $GITHUB_OUTPUT

backend/.env.docker

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,11 @@ LOKI_USERNAME=""
2929
LOKI_PASSWORD=""
3030

3131
# Kafka / Redpanda configuration for node I/O, log, and event ingestion (Docker network)
32-
LOG_KAFKA_BROKERS="redpanda:9092"
32+
LOG_KAFKA_BROKERS="redpanda:9092"
33+
34+
35+
# GitHub template repository configuration
36+
GITHUB_TEMPLATE_REPO=shipsecai/workflow-templates
37+
GITHUB_TEMPLATE_BRANCH=main
38+
# Optional: GitHub personal access token for higher rate limits (60/hr → 5000/hr)
39+
GITHUB_TEMPLATE_TOKEN=
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
-- Create templates table
2+
CREATE TABLE "templates" (
3+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
4+
"name" varchar(255) NOT NULL,
5+
"description" text,
6+
"category" varchar(100),
7+
"tags" jsonb DEFAULT '[]'::jsonb NOT NULL,
8+
"author" varchar(255),
9+
"repository" varchar(255) NOT NULL,
10+
"path" varchar(500) NOT NULL,
11+
"branch" varchar(100) DEFAULT 'main' NOT NULL,
12+
"version" varchar(50),
13+
"commit_sha" varchar(100),
14+
"manifest" jsonb NOT NULL,
15+
"graph" jsonb,
16+
"required_secrets" jsonb DEFAULT '[]'::jsonb NOT NULL,
17+
"popularity" integer DEFAULT 0 NOT NULL,
18+
"is_official" boolean DEFAULT false NOT NULL,
19+
"is_verified" boolean DEFAULT false NOT NULL,
20+
"is_active" boolean DEFAULT true NOT NULL,
21+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
22+
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
23+
);
24+
--> statement-breakpoint
25+
-- Create templates_submissions table
26+
CREATE TABLE "templates_submissions" (
27+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
28+
"template_name" varchar(255) NOT NULL,
29+
"description" text,
30+
"category" varchar(100),
31+
"repository" varchar(255) NOT NULL,
32+
"branch" varchar(100),
33+
"path" varchar(500) NOT NULL,
34+
"commit_sha" varchar(100),
35+
"pr_number" integer,
36+
"pr_url" varchar(500),
37+
"status" varchar(50) DEFAULT 'pending' NOT NULL,
38+
"submitted_by" varchar(191) NOT NULL,
39+
"organization_id" varchar(191),
40+
"manifest" jsonb,
41+
"graph" jsonb,
42+
"feedback" text,
43+
"reviewed_by" varchar(191),
44+
"reviewed_at" timestamp with time zone,
45+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
46+
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
47+
);
48+
--> statement-breakpoint
49+
-- Create indexes for templates
50+
CREATE INDEX "templates_repository_path_idx" ON "templates" ("repository", "path");
51+
CREATE INDEX "templates_category_idx" ON "templates" ("category");
52+
CREATE INDEX "templates_is_active_idx" ON "templates" ("is_active");
53+
CREATE INDEX "templates_popularity_idx" ON "templates" ("popularity" DESC);
54+
--> statement-breakpoint
55+
-- Create indexes for templates_submissions
56+
CREATE INDEX "templates_submissions_pr_number_idx" ON "templates_submissions" ("pr_number");
57+
CREATE INDEX "templates_submissions_submitted_by_idx" ON "templates_submissions" ("submitted_by");
58+
CREATE INDEX "templates_submissions_status_idx" ON "templates_submissions" ("status");
59+
CREATE INDEX "templates_submissions_organization_id_idx" ON "templates_submissions" ("organization_id");

backend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"bcryptjs": "^3.0.3",
4646
"class-transformer": "^0.5.1",
4747
"class-validator": "^0.14.3",
48+
"cookie-parser": "^1.4.7",
4849
"date-fns": "^4.1.0",
4950
"dotenv": "^17.2.3",
5051
"drizzle-orm": "^0.44.7",

backend/src/app.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { WebhooksModule } from './webhooks/webhooks.module';
3434
import { HumanInputsModule } from './human-inputs/human-inputs.module';
3535
import { McpServersModule } from './mcp-servers/mcp-servers.module';
3636
import { McpGroupsModule } from './mcp-groups/mcp-groups.module';
37+
import { TemplatesModule } from './templates/templates.module';
3738

3839
const coreModules = [
3940
AgentsModule,
@@ -53,6 +54,7 @@ const coreModules = [
5354
McpGroupsModule,
5455
McpModule,
5556
StudioMcpModule,
57+
TemplatesModule,
5658
AuditModule,
5759
];
5860

backend/src/config/env.schema.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ export const backendEnvSchema = z
7575
PLATFORM_SERVICE_TOKEN: z.string().optional().default(''),
7676
PLATFORM_API_TIMEOUT_MS: z.string().optional().default(''),
7777

78+
// --- GitHub Template Library ---
79+
GITHUB_TEMPLATE_REPO: z
80+
.string()
81+
.optional()
82+
.default('shipsecai/workflow-templates')
83+
.refine((v) => v.includes('/'), {
84+
message: 'GITHUB_TEMPLATE_REPO must be in owner/repo format',
85+
}),
86+
GITHUB_TEMPLATE_BRANCH: z.string().optional().default('main'),
87+
GITHUB_TEMPLATE_TOKEN: z.string().optional(),
88+
7889
// --- Temporal ---
7990
TEMPORAL_BOOTSTRAP_DEMO: stringToBoolean(false),
8091
})

backend/src/database/schema/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ export * from './mcp-servers';
2121

2222
export * from './node-io';
2323
export * from './organization-settings';
24+
export * from './templates';
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import {
2+
pgTable,
3+
uuid,
4+
varchar,
5+
text,
6+
timestamp,
7+
jsonb,
8+
boolean,
9+
integer,
10+
} from 'drizzle-orm/pg-core';
11+
import { z } from 'zod';
12+
13+
/**
14+
* Templates table - stores workflow template metadata
15+
* Templates are synced from GitHub repository
16+
*/
17+
export const templatesTable = pgTable('templates', {
18+
id: uuid('id').primaryKey().defaultRandom(),
19+
name: varchar('name', { length: 255 }).notNull(),
20+
description: text('description'),
21+
category: varchar('category', { length: 100 }),
22+
tags: jsonb('tags').$type<string[]>().default([]),
23+
author: varchar('author', { length: 255 }),
24+
// GitHub repository info
25+
repository: varchar('repository', { length: 255 }).notNull(), // e.g., "org/templates"
26+
path: varchar('path', { length: 500 }).notNull(), // Path to template in repo
27+
branch: varchar('branch', { length: 100 }).default('main'),
28+
version: varchar('version', { length: 50 }), // Optional version tag
29+
commitSha: varchar('commit_sha', { length: 100 }),
30+
// Template content
31+
manifest: jsonb('manifest').$type<TemplateManifest>().notNull(),
32+
graph: jsonb('graph').$type<Record<string, unknown>>(), // Sanitized workflow graph
33+
requiredSecrets: jsonb('required_secrets').$type<RequiredSecret[]>().default([]),
34+
// Stats and flags
35+
popularity: integer('popularity').notNull().default(0),
36+
isOfficial: boolean('is_official').notNull().default(false),
37+
isVerified: boolean('is_verified').notNull().default(false),
38+
isActive: boolean('is_active').notNull().default(true),
39+
// Timestamps
40+
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
41+
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
42+
});
43+
44+
/**
45+
* Template submissions table - tracks PR-based template submissions
46+
*/
47+
export const templatesSubmissionsTable = pgTable('templates_submissions', {
48+
id: uuid('id').primaryKey().defaultRandom(),
49+
templateName: varchar('template_name', { length: 255 }).notNull(),
50+
description: text('description'),
51+
category: varchar('category', { length: 100 }),
52+
repository: varchar('repository', { length: 255 }).notNull(),
53+
branch: varchar('branch', { length: 100 }),
54+
path: varchar('path', { length: 500 }).notNull(),
55+
commitSha: varchar('commit_sha', { length: 100 }),
56+
pullRequestNumber: integer('pr_number'),
57+
pullRequestUrl: varchar('pr_url', { length: 500 }),
58+
status: varchar('status', { length: 50 }).notNull().default('pending'), // pending, approved, rejected, merged
59+
submittedBy: varchar('submitted_by', { length: 191 }).notNull(),
60+
organizationId: varchar('organization_id', { length: 191 }),
61+
manifest: jsonb('manifest').$type<TemplateManifest>(),
62+
graph: jsonb('graph').$type<Record<string, unknown>>(),
63+
feedback: text('feedback'),
64+
reviewedBy: varchar('reviewed_by', { length: 191 }),
65+
reviewedAt: timestamp('reviewed_at', { withTimezone: true }),
66+
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
67+
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
68+
});
69+
70+
// Zod schemas for validation
71+
export const RequiredSecretSchema = z.object({
72+
name: z.string(),
73+
type: z.string(),
74+
description: z.string().optional(),
75+
placeholder: z.string().optional(),
76+
});
77+
78+
export const TemplateManifestSchema = z.object({
79+
name: z.string(),
80+
description: z.string().optional(),
81+
version: z.string().optional(),
82+
author: z.string().optional(),
83+
category: z.string().optional(),
84+
tags: z.array(z.string()).optional(),
85+
requiredSecrets: z.array(RequiredSecretSchema).optional(),
86+
entryPoint: z.string().optional(),
87+
screenshots: z.array(z.string()).optional(),
88+
documentation: z.string().optional(),
89+
});
90+
91+
// Type exports
92+
export type TemplateManifest = z.infer<typeof TemplateManifestSchema>;
93+
export type RequiredSecret = z.infer<typeof RequiredSecretSchema>;
94+
95+
export type Template = typeof templatesTable.$inferSelect;
96+
export type NewTemplate = typeof templatesTable.$inferInsert;
97+
98+
export type TemplateSubmission = typeof templatesSubmissionsTable.$inferSelect;
99+
export type NewTemplateSubmission = typeof templatesSubmissionsTable.$inferInsert;

0 commit comments

Comments
 (0)