Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
1b26269
feat: add initial implementation of pipeline UI package
luxass Jan 31, 2026
f3e42a7
feat(pipelines): implement cache key and store interfaces
luxass Jan 18, 2026
a44fa5c
WIP
luxass Jan 31, 2026
787478b
feat(pipeline-presets): add standard and unicode data parsers
luxass Jan 19, 2026
cd7ea18
chore: add ESLint configuration files
luxass Jan 19, 2026
1f1e562
chore: lint
luxass Jan 19, 2026
802a155
chore: lint
luxass Jan 19, 2026
ecfda3f
chore: update build and dev script filters
luxass Jan 20, 2026
ef318dc
chore: update eslint config to beta.2 and add tinyglobby
luxass Jan 20, 2026
d0177c9
WIP
luxass Jan 20, 2026
135cf05
feat: enhance pipeline definition options and type inference
luxass Jan 20, 2026
b770138
chore: remove main and module fields from package.json
luxass Jan 31, 2026
d971cc0
refactor(pipeline-loader): remove unused loadPipelines function
luxass Jan 31, 2026
840f361
feat(pipeline-loader): add vitest-testdirs for testing support
luxass Jan 31, 2026
4fc2fb4
WIP: first draft of pipeline ui
luxass Feb 1, 2026
5f934ae
WIP: first draft of the Pipeline Server
luxass Feb 1, 2026
4224343
WIP: doesn't work right now. AI generated most of it.
luxass Feb 1, 2026
feaf778
refactor(pipeline-loader): update findPipelineFiles interface
luxass Feb 1, 2026
990056f
feat(pipeline-ui): update styles and components for new design
luxass Feb 4, 2026
8778609
refactor(pipeline-artifacts): improve type assertions in tests
luxass Feb 4, 2026
a3c6246
feat(pipeline-core): add 'id' field to event interfaces and create Pi…
luxass Feb 4, 2026
6a385ce
feat(pipeline-executor): add event ID generation for emitted events
luxass Feb 4, 2026
ad29b2c
fix(pipeline-loader): ignore Vite processing for dynamic imports
luxass Feb 4, 2026
59433ca
feat(pipeline-server): add components for log viewing and interaction
luxass Feb 4, 2026
be30171
WIP
luxass Feb 5, 2026
f079759
chore(pipeline-*): update `publint`, `tsdown`, and `typescript` to us…
luxass Feb 5, 2026
fcf8a90
chore(shared-ui): update import paths in CSS files
luxass Feb 5, 2026
67f4056
chore(pipeline-server): update dependencies to use catalog references
luxass Feb 5, 2026
9063f6a
chore(pipeline-server): add `esrap` and `oxc-parser` to catalogs
luxass Feb 5, 2026
a6ce49c
feat(shared-ui): add Checkbox component to UI library
luxass Feb 5, 2026
bb5fa6a
feat(pipeline-server): add command palette and context menu components
luxass Feb 5, 2026
60d61d7
feat(pipeline-server): enhance PipelineCommandPalette with Command co…
luxass Feb 5, 2026
b927849
chore: add roadmap for ideas
luxass Feb 5, 2026
cf2357b
feat(test-utils): add async iterable utilities and tests
luxass Feb 5, 2026
6443dbc
feat(pipeline-core): enhance transform definitions and tests
luxass Feb 5, 2026
fbd26a7
feat(pipeline-loader): add oxc-transform dependency and enhance loade…
luxass Feb 5, 2026
dcb97e0
feat(test-utils): export async utilities from async module
luxass Feb 5, 2026
673dc50
feat(pipeline-ui): add new components and update dependencies
luxass Feb 5, 2026
dbd7636
WIP
luxass Feb 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Pipeline Server v2.0 Roadmap

## Phase 1: Authentication & Deployment Foundation

### 1.1 Cloudflare Workers Migration
- Move from Node.js server to Cloudflare Workers
- Use Durable Objects for stateful operations
- KV storage for caching
- D1 database for persistence

### 1.2 Authentication Strategy
- **Local Development**: Nuxt DevTools-style auth (simple, no external deps)
- **Production**: GitHub OAuth (leverage existing GitHub integration)
- JWT tokens with refresh mechanism
- Role-based access (viewer, editor, admin)

### 1.3 GitHub Integration
- OAuth app for repository access
- Webhook support for pipeline file changes
- Read `.ucd-pipeline.ts` files from repos
- Sync pipeline definitions with GitHub

## Phase 2: Core Features

### 2.1 Multi-tenant Support
- Organizations/teams
- Repository-level permissions
- Pipeline sharing between teams

### 2.2 Advanced Execution
- Queue system for pipeline runs
- Concurrent execution limits
- Execution history retention
- Scheduled/cron jobs

### 2.3 Collaboration Features
- Comments on pipeline executions
- Share execution results via links
- Export/import pipeline configs

## Phase 3: UI/UX Overhaul

### 3.1 Design System
- Consistent component library
- Dark/light mode
- Responsive layouts
- Accessibility (WCAG 2.1)

### 3.2 Pipeline Visualizer Improvements
- Interactive graph editing
- Real-time execution visualization
- Performance profiling
- Bottleneck detection

### 3.3 Mobile Support
- Responsive sidebar
- Touch-friendly interactions
- Mobile-optimized views

## Phase 4: Developer Experience

### 4.1 VS Code Extension
- Edit pipelines in IDE
- Live preview
- Auto-completion
- One-click deploy

### 4.2 CLI Improvements
- Remote pipeline management
- CI/CD integration
- Deployment commands

### 4.3 API & SDK
- RESTful API
- TypeScript SDK
- WebSocket for real-time updates

## Technical Considerations

### Architecture Changes
- Move to edge functions (Cloudflare)
- Separate compute from storage
- Event-driven architecture
- GraphQL for flexible queries

### Data Model

```typescript
// Organizations
interface Organization {
id: string;
name: string;
githubInstallationId: string;
}

// Repositories
interface Repository {
id: string;
orgId: string;
fullName: string; // owner/repo
pipelines: Pipeline[];
}

// Users
interface User {
id: string;
githubId: string;
orgs: string[];
role: 'viewer' | 'editor' | 'admin';
}
```

### Security
- Encrypted tokens at rest
- Rate limiting
- Audit logs
- Secret management for pipeline configs

## Priority Order

1. **Authentication** (Nuxt DevTools style for local)
2. **Cloudflare Workers migration**
3. **GitHub OAuth & repo sync**
4. **UI overhaul** (fix context menus, actions)
5. **Multi-tenant/teams**
6. **Advanced features** (scheduler, webhooks)

---

*Last updated: February 2026*
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"@tanstack/react-router-ssr-query": "catalog:web",
"@tanstack/react-start": "catalog:web",
"@ucdjs-internal/shared-ui": "workspace:*",
"@ucdjs/pipelines-ui": "workspace:*",
"@ucdjs/schemas": "workspace:*",
"@ucdjs/ucd-store": "workspace:*",
"@unicode-utils/core": "catalog:prod",
Expand Down
3 changes: 2 additions & 1 deletion apps/web/src/components/layout/sidebar/app-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
SidebarMenuItem,
SidebarRail,
} from "@ucdjs-internal/shared-ui/ui/sidebar";
import { BookOpen, ExternalLink, Grid3X3, Lightbulb, Search, Type } from "lucide-react";
import { BookOpen, ExternalLink, GitGraph, Grid3X3, Lightbulb, Search, Type } from "lucide-react";
import { UcdLogo } from "../../ucd-logo";
import { VersionSwitcher } from "../../version-switcher";

Expand All @@ -33,6 +33,7 @@ const VERSION_ITEMS = [

const TOOLS_ITEMS = [
{ to: "/file-explorer/$", params: { _splat: "" }, icon: BookOpen, label: "File Explorer" },
{ to: "/pipeline-graph", icon: GitGraph, label: "Pipeline Graph" },
] as const;

export function AppSidebar({ ...props }: ComponentProps<typeof Sidebar>) {
Expand Down
21 changes: 21 additions & 0 deletions apps/web/src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import { Route as rootRouteImport } from './routes/__root'
import { Route as SearchRouteImport } from './routes/search'
import { Route as PipelineGraphRouteImport } from './routes/pipeline-graph'
import { Route as CodepointInspectorRouteImport } from './routes/codepoint-inspector'
import { Route as FileExplorerRouteRouteImport } from './routes/file-explorer/route'
import { Route as IndexRouteImport } from './routes/index'
Expand All @@ -31,6 +32,11 @@ const SearchRoute = SearchRouteImport.update({
path: '/search',
getParentRoute: () => rootRouteImport,
} as any)
const PipelineGraphRoute = PipelineGraphRouteImport.update({
id: '/pipeline-graph',
path: '/pipeline-graph',
getParentRoute: () => rootRouteImport,
} as any)
const CodepointInspectorRoute = CodepointInspectorRouteImport.update({
id: '/codepoint-inspector',
path: '/codepoint-inspector',
Expand Down Expand Up @@ -113,6 +119,7 @@ export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/file-explorer': typeof FileExplorerRouteRouteWithChildren
'/codepoint-inspector': typeof CodepointInspectorRoute
'/pipeline-graph': typeof PipelineGraphRoute
'/search': typeof SearchRoute
'/v/$version': typeof VVersionRouteRouteWithChildren
'/file-explorer/$': typeof FileExplorerSplatRoute
Expand All @@ -131,6 +138,7 @@ export interface FileRoutesByTo {
'/': typeof IndexRoute
'/file-explorer': typeof FileExplorerRouteRouteWithChildren
'/codepoint-inspector': typeof CodepointInspectorRoute
'/pipeline-graph': typeof PipelineGraphRoute
'/search': typeof SearchRoute
'/file-explorer/$': typeof FileExplorerSplatRoute
'/v': typeof VIndexRoute
Expand All @@ -149,6 +157,7 @@ export interface FileRoutesById {
'/': typeof IndexRoute
'/file-explorer': typeof FileExplorerRouteRouteWithChildren
'/codepoint-inspector': typeof CodepointInspectorRoute
'/pipeline-graph': typeof PipelineGraphRoute
'/search': typeof SearchRoute
'/v/$version': typeof VVersionRouteRouteWithChildren
'/file-explorer/$': typeof FileExplorerSplatRoute
Expand All @@ -169,6 +178,7 @@ export interface FileRouteTypes {
| '/'
| '/file-explorer'
| '/codepoint-inspector'
| '/pipeline-graph'
| '/search'
| '/v/$version'
| '/file-explorer/$'
Expand All @@ -187,6 +197,7 @@ export interface FileRouteTypes {
| '/'
| '/file-explorer'
| '/codepoint-inspector'
| '/pipeline-graph'
| '/search'
| '/file-explorer/$'
| '/v'
Expand All @@ -204,6 +215,7 @@ export interface FileRouteTypes {
| '/'
| '/file-explorer'
| '/codepoint-inspector'
| '/pipeline-graph'
| '/search'
| '/v/$version'
| '/file-explorer/$'
Expand All @@ -223,6 +235,7 @@ export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
FileExplorerRouteRoute: typeof FileExplorerRouteRouteWithChildren
CodepointInspectorRoute: typeof CodepointInspectorRoute
PipelineGraphRoute: typeof PipelineGraphRoute
SearchRoute: typeof SearchRoute
VVersionRouteRoute: typeof VVersionRouteRouteWithChildren
VIndexRoute: typeof VIndexRoute
Expand All @@ -237,6 +250,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof SearchRouteImport
parentRoute: typeof rootRouteImport
}
'/pipeline-graph': {
id: '/pipeline-graph'
path: '/pipeline-graph'
fullPath: '/pipeline-graph'
preLoaderRoute: typeof PipelineGraphRouteImport
parentRoute: typeof rootRouteImport
}
'/codepoint-inspector': {
id: '/codepoint-inspector'
path: '/codepoint-inspector'
Expand Down Expand Up @@ -388,6 +408,7 @@ const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
FileExplorerRouteRoute: FileExplorerRouteRouteWithChildren,
CodepointInspectorRoute: CodepointInspectorRoute,
PipelineGraphRoute: PipelineGraphRoute,
SearchRoute: SearchRoute,
VVersionRouteRoute: VVersionRouteRouteWithChildren,
VIndexRoute: VIndexRoute,
Expand Down
82 changes: 82 additions & 0 deletions apps/web/src/routes/pipeline-graph.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import type { PipelineGraph as PipelineGraphType } from "@ucdjs/pipelines-core";
import { createFileRoute, Link } from "@tanstack/react-router";
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "@ucdjs-internal/shared-ui/ui/breadcrumb";
import { PipelineGraph } from "@ucdjs/pipelines-ui";

export const Route = createFileRoute("/pipeline-graph")({
component: PipelineGraphPage,
});

// Fake data for testing the visualization
const fakeGraph: PipelineGraphType = {
nodes: [
{ id: "source-16.0.0", type: "source", version: "16.0.0" },
{ id: "file-ucd-linebreak", type: "file", file: { version: "16.0.0", dir: "ucd", path: "ucd/LineBreak.txt", name: "LineBreak.txt", ext: ".txt" } },
{ id: "file-ucd-unicodedata", type: "file", file: { version: "16.0.0", dir: "ucd", path: "ucd/UnicodeData.txt", name: "UnicodeData.txt", ext: ".txt" } },
{ id: "file-ucd-blocks", type: "file", file: { version: "16.0.0", dir: "ucd", path: "ucd/Blocks.txt", name: "Blocks.txt", ext: ".txt" } },
{ id: "file-emoji-data", type: "file", file: { version: "16.0.0", dir: "emoji", path: "emoji/emoji-data.txt", name: "emoji-data.txt", ext: ".txt" } },
{ id: "route-linebreak", type: "route", routeId: "linebreak" },
{ id: "route-unicodedata", type: "route", routeId: "unicode-data" },
{ id: "route-blocks", type: "route", routeId: "blocks" },
{ id: "route-emoji", type: "route", routeId: "emoji-properties" },
{ id: "artifact-linebreak-json", type: "artifact", artifactId: "linebreak.json" },
{ id: "artifact-characters-json", type: "artifact", artifactId: "characters.json" },
{ id: "artifact-blocks-json", type: "artifact", artifactId: "blocks.json" },
{ id: "artifact-emoji-json", type: "artifact", artifactId: "emoji.json" },
{ id: "output-0", type: "output", outputIndex: 0 },
{ id: "output-1", type: "output", outputIndex: 1 },
{ id: "output-2", type: "output", outputIndex: 2 },
{ id: "output-3", type: "output", outputIndex: 3 },
],
edges: [
{ from: "source-16.0.0", to: "file-ucd-linebreak", type: "provides" },
{ from: "source-16.0.0", to: "file-ucd-unicodedata", type: "provides" },
{ from: "source-16.0.0", to: "file-ucd-blocks", type: "provides" },
{ from: "source-16.0.0", to: "file-emoji-data", type: "provides" },
{ from: "file-ucd-linebreak", to: "route-linebreak", type: "matched" },
{ from: "file-ucd-unicodedata", to: "route-unicodedata", type: "matched" },
{ from: "file-ucd-blocks", to: "route-blocks", type: "matched" },
{ from: "file-emoji-data", to: "route-emoji", type: "matched" },
{ from: "route-linebreak", to: "artifact-linebreak-json", type: "parsed" },
{ from: "route-unicodedata", to: "artifact-characters-json", type: "parsed" },
{ from: "route-blocks", to: "artifact-blocks-json", type: "parsed" },
{ from: "route-emoji", to: "artifact-emoji-json", type: "parsed" },
{ from: "artifact-linebreak-json", to: "output-0", type: "resolved" },
{ from: "artifact-characters-json", to: "output-1", type: "resolved" },
{ from: "artifact-blocks-json", to: "output-2", type: "resolved" },
{ from: "artifact-emoji-json", to: "output-3", type: "resolved" },
// Cross-artifact dependency example
{ from: "artifact-characters-json", to: "artifact-emoji-json", type: "uses-artifact" },
],
};

function PipelineGraphPage() {
return (
<div className="flex flex-1 flex-col h-full">
<header className="flex items-center gap-4 p-4 border-b border-gray-200 dark:border-gray-800">
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink render={<Link to="/">Home</Link>} />
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Pipeline Graph</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</header>

<div className="flex-1 min-h-0">
<PipelineGraph
graph={fakeGraph}
onNodeSelect={(node) => {
if (node) {
console.log("Selected node:", node);
}
}}
/>
</div>
</div>
);
}
2 changes: 2 additions & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
"@ucdjs/env": "workspace:*",
"@ucdjs/fs-bridge": "workspace:*",
"@ucdjs/lockfile": "workspace:*",
"@ucdjs/pipelines-loader": "workspace:*",
"@ucdjs/pipelines-server": "workspace:*",
"@ucdjs/schema-gen": "workspace:*",
"@ucdjs/schemas": "workspace:*",
"@ucdjs/ucd-store": "workspace:*",
Expand Down
Loading