@d34dman/flowdrop 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +293 -0
- package/dist/adapters/WorkflowAdapter.d.ts +166 -0
- package/dist/adapters/WorkflowAdapter.js +337 -0
- package/dist/api/client.d.ts +79 -0
- package/dist/api/client.js +208 -0
- package/dist/app.css +0 -0
- package/dist/clients/ApiClient.d.ts +203 -0
- package/dist/clients/ApiClient.js +212 -0
- package/dist/components/App.svelte +237 -0
- package/dist/components/App.svelte.d.ts +3 -0
- package/dist/components/CanvasBanner.svelte +51 -0
- package/dist/components/CanvasBanner.svelte.d.ts +22 -0
- package/dist/components/LoadingSpinner.svelte +36 -0
- package/dist/components/LoadingSpinner.svelte.d.ts +8 -0
- package/dist/components/Node.svelte +38 -0
- package/dist/components/Node.svelte.d.ts +4 -0
- package/dist/components/NodeSidebar.svelte +500 -0
- package/dist/components/NodeSidebar.svelte.d.ts +9 -0
- package/dist/components/WorkflowEditor.svelte +542 -0
- package/dist/components/WorkflowEditor.svelte.d.ts +10 -0
- package/dist/components/WorkflowNode.svelte +558 -0
- package/dist/components/WorkflowNode.svelte.d.ts +11 -0
- package/dist/data/samples.d.ts +17 -0
- package/dist/data/samples.js +1193 -0
- package/dist/examples/adapter-usage.d.ts +66 -0
- package/dist/examples/adapter-usage.js +138 -0
- package/dist/examples/api-client-usage.d.ts +31 -0
- package/dist/examples/api-client-usage.js +241 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +27 -0
- package/dist/services/api.d.ts +110 -0
- package/dist/services/api.js +149 -0
- package/dist/services/workflowStorage.d.ts +37 -0
- package/dist/services/workflowStorage.js +116 -0
- package/dist/styles/base.css +858 -0
- package/dist/svelte-app.d.ts +17 -0
- package/dist/svelte-app.js +30 -0
- package/dist/types/index.d.ts +179 -0
- package/dist/types/index.js +4 -0
- package/dist/utils/colors.d.ts +121 -0
- package/dist/utils/colors.js +240 -0
- package/dist/utils/connections.d.ts +47 -0
- package/dist/utils/connections.js +240 -0
- package/dist/utils/icons.d.ts +102 -0
- package/dist/utils/icons.js +149 -0
- package/package.json +99 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side API service for FlowDrop
|
|
3
|
+
* Provides methods to interact with the backend APIs
|
|
4
|
+
*/
|
|
5
|
+
let API_BASE = "/api";
|
|
6
|
+
/**
|
|
7
|
+
* Set the API base URL at runtime
|
|
8
|
+
*/
|
|
9
|
+
export function setApiBaseUrl(url) {
|
|
10
|
+
API_BASE = url;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Generic API request helper
|
|
14
|
+
*/
|
|
15
|
+
async function apiRequest(endpoint, options = {}) {
|
|
16
|
+
try {
|
|
17
|
+
const response = await fetch(`${API_BASE}${endpoint}`, {
|
|
18
|
+
headers: {
|
|
19
|
+
"Content-Type": "application/json",
|
|
20
|
+
...options.headers
|
|
21
|
+
},
|
|
22
|
+
...options
|
|
23
|
+
});
|
|
24
|
+
const data = await response.json();
|
|
25
|
+
if (!response.ok) {
|
|
26
|
+
throw new Error(data.error || `HTTP ${response.status}: ${response.statusText}`);
|
|
27
|
+
}
|
|
28
|
+
return data;
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
console.error(`API request failed for ${endpoint}:`, error);
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Node API methods
|
|
37
|
+
*/
|
|
38
|
+
export const nodeApi = {
|
|
39
|
+
/**
|
|
40
|
+
* Get all node types with optional filtering
|
|
41
|
+
*/
|
|
42
|
+
async getNodes(options) {
|
|
43
|
+
const params = new URLSearchParams();
|
|
44
|
+
if (options?.category)
|
|
45
|
+
params.append("category", options.category);
|
|
46
|
+
if (options?.search)
|
|
47
|
+
params.append("search", options.search);
|
|
48
|
+
if (options?.limit)
|
|
49
|
+
params.append("limit", options.limit.toString());
|
|
50
|
+
if (options?.offset)
|
|
51
|
+
params.append("offset", options.offset.toString());
|
|
52
|
+
const response = await apiRequest("/nodes?" + params.toString());
|
|
53
|
+
return response.data || [];
|
|
54
|
+
},
|
|
55
|
+
/**
|
|
56
|
+
* Get a specific node type by ID
|
|
57
|
+
*/
|
|
58
|
+
async getNode(id) {
|
|
59
|
+
const response = await apiRequest(`/nodes/${id}`);
|
|
60
|
+
if (!response.data) {
|
|
61
|
+
throw new Error("Node not found");
|
|
62
|
+
}
|
|
63
|
+
return response.data;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Workflow API methods
|
|
68
|
+
*/
|
|
69
|
+
export const workflowApi = {
|
|
70
|
+
/**
|
|
71
|
+
* Get all workflows with optional filtering
|
|
72
|
+
*/
|
|
73
|
+
async getWorkflows(options) {
|
|
74
|
+
const params = new URLSearchParams();
|
|
75
|
+
if (options?.search)
|
|
76
|
+
params.append("search", options.search);
|
|
77
|
+
if (options?.limit)
|
|
78
|
+
params.append("limit", options.limit.toString());
|
|
79
|
+
if (options?.offset)
|
|
80
|
+
params.append("offset", options.offset.toString());
|
|
81
|
+
const response = await apiRequest("/workflows?" + params.toString());
|
|
82
|
+
return response.data || [];
|
|
83
|
+
},
|
|
84
|
+
/**
|
|
85
|
+
* Get a specific workflow by ID
|
|
86
|
+
*/
|
|
87
|
+
async getWorkflow(id) {
|
|
88
|
+
const response = await apiRequest(`/workflows/${id}`);
|
|
89
|
+
if (!response.data) {
|
|
90
|
+
throw new Error("Workflow not found");
|
|
91
|
+
}
|
|
92
|
+
return response.data;
|
|
93
|
+
},
|
|
94
|
+
/**
|
|
95
|
+
* Create a new workflow
|
|
96
|
+
*/
|
|
97
|
+
async createWorkflow(workflow) {
|
|
98
|
+
const response = await apiRequest("/workflows", {
|
|
99
|
+
method: "POST",
|
|
100
|
+
body: JSON.stringify(workflow)
|
|
101
|
+
});
|
|
102
|
+
if (!response.data) {
|
|
103
|
+
throw new Error("Failed to create workflow");
|
|
104
|
+
}
|
|
105
|
+
return response.data;
|
|
106
|
+
},
|
|
107
|
+
/**
|
|
108
|
+
* Update an existing workflow
|
|
109
|
+
*/
|
|
110
|
+
async updateWorkflow(id, workflow) {
|
|
111
|
+
const response = await apiRequest(`/workflows/${id}`, {
|
|
112
|
+
method: "PUT",
|
|
113
|
+
body: JSON.stringify(workflow)
|
|
114
|
+
});
|
|
115
|
+
if (!response.data) {
|
|
116
|
+
throw new Error("Failed to update workflow");
|
|
117
|
+
}
|
|
118
|
+
return response.data;
|
|
119
|
+
},
|
|
120
|
+
/**
|
|
121
|
+
* Delete a workflow
|
|
122
|
+
*/
|
|
123
|
+
async deleteWorkflow(id) {
|
|
124
|
+
await apiRequest(`/workflows/${id}`, {
|
|
125
|
+
method: "DELETE"
|
|
126
|
+
});
|
|
127
|
+
},
|
|
128
|
+
/**
|
|
129
|
+
* Save workflow (create or update)
|
|
130
|
+
*/
|
|
131
|
+
async saveWorkflow(workflow) {
|
|
132
|
+
if (workflow.id && workflow.id.length === 36) {
|
|
133
|
+
// Update existing workflow (UUID is 36 characters)
|
|
134
|
+
return this.updateWorkflow(workflow.id, workflow);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
// Create new workflow
|
|
138
|
+
const { id, ...workflowData } = workflow;
|
|
139
|
+
return this.createWorkflow(workflowData);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Export the API service
|
|
145
|
+
*/
|
|
146
|
+
export const api = {
|
|
147
|
+
nodes: nodeApi,
|
|
148
|
+
workflows: workflowApi
|
|
149
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory workflow storage service
|
|
3
|
+
* This can be replaced with a database implementation later
|
|
4
|
+
*/
|
|
5
|
+
import type { Workflow } from "../types/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* Save a workflow
|
|
8
|
+
*/
|
|
9
|
+
export declare function saveWorkflow(workflow: Omit<Workflow, "id">): Promise<Workflow>;
|
|
10
|
+
/**
|
|
11
|
+
* Update an existing workflow
|
|
12
|
+
*/
|
|
13
|
+
export declare function updateWorkflow(id: string, workflow: Partial<Workflow>): Promise<Workflow | null>;
|
|
14
|
+
/**
|
|
15
|
+
* Get a workflow by ID
|
|
16
|
+
*/
|
|
17
|
+
export declare function getWorkflow(id: string): Promise<Workflow | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Get all workflows with optional filtering
|
|
20
|
+
*/
|
|
21
|
+
export declare function getWorkflows(options?: {
|
|
22
|
+
search?: string;
|
|
23
|
+
limit?: number;
|
|
24
|
+
offset?: number;
|
|
25
|
+
}): Promise<Workflow[]>;
|
|
26
|
+
/**
|
|
27
|
+
* Delete a workflow
|
|
28
|
+
*/
|
|
29
|
+
export declare function deleteWorkflow(id: string): Promise<boolean>;
|
|
30
|
+
/**
|
|
31
|
+
* Get workflow count
|
|
32
|
+
*/
|
|
33
|
+
export declare function getWorkflowCount(): Promise<number>;
|
|
34
|
+
/**
|
|
35
|
+
* Initialize with sample workflows (for development)
|
|
36
|
+
*/
|
|
37
|
+
export declare function initializeSampleWorkflows(): Promise<void>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory workflow storage service
|
|
3
|
+
* This can be replaced with a database implementation later
|
|
4
|
+
*/
|
|
5
|
+
import { v4 as uuidv4 } from "uuid";
|
|
6
|
+
// In-memory storage
|
|
7
|
+
const workflows = new Map();
|
|
8
|
+
/**
|
|
9
|
+
* Generate a unique workflow ID using UUID v4
|
|
10
|
+
*/
|
|
11
|
+
function generateWorkflowId() {
|
|
12
|
+
return uuidv4();
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Save a workflow
|
|
16
|
+
*/
|
|
17
|
+
export async function saveWorkflow(workflow) {
|
|
18
|
+
const id = generateWorkflowId();
|
|
19
|
+
const newWorkflow = {
|
|
20
|
+
...workflow,
|
|
21
|
+
id,
|
|
22
|
+
metadata: {
|
|
23
|
+
version: "1.0.0",
|
|
24
|
+
createdAt: new Date().toISOString(),
|
|
25
|
+
updatedAt: new Date().toISOString(),
|
|
26
|
+
...workflow.metadata
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
workflows.set(id, newWorkflow);
|
|
30
|
+
return newWorkflow;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Update an existing workflow
|
|
34
|
+
*/
|
|
35
|
+
export async function updateWorkflow(id, workflow) {
|
|
36
|
+
const existing = workflows.get(id);
|
|
37
|
+
if (!existing) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
const updatedWorkflow = {
|
|
41
|
+
...existing,
|
|
42
|
+
...workflow,
|
|
43
|
+
id, // Ensure ID doesn't change
|
|
44
|
+
metadata: {
|
|
45
|
+
version: existing.metadata?.version || "1.0.0",
|
|
46
|
+
createdAt: existing.metadata?.createdAt || new Date().toISOString(),
|
|
47
|
+
updatedAt: new Date().toISOString(),
|
|
48
|
+
author: workflow.metadata?.author || existing.metadata?.author,
|
|
49
|
+
tags: workflow.metadata?.tags || existing.metadata?.tags
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
workflows.set(id, updatedWorkflow);
|
|
53
|
+
return updatedWorkflow;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get a workflow by ID
|
|
57
|
+
*/
|
|
58
|
+
export async function getWorkflow(id) {
|
|
59
|
+
return workflows.get(id) || null;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get all workflows with optional filtering
|
|
63
|
+
*/
|
|
64
|
+
export async function getWorkflows(options) {
|
|
65
|
+
let filteredWorkflows = Array.from(workflows.values());
|
|
66
|
+
// Apply search filter
|
|
67
|
+
if (options?.search) {
|
|
68
|
+
const searchLower = options.search.toLowerCase();
|
|
69
|
+
filteredWorkflows = filteredWorkflows.filter(workflow => workflow.name.toLowerCase().includes(searchLower) ||
|
|
70
|
+
workflow.description?.toLowerCase().includes(searchLower) ||
|
|
71
|
+
workflow.metadata?.tags?.some(tag => tag.toLowerCase().includes(searchLower)));
|
|
72
|
+
}
|
|
73
|
+
// Sort by updated date (newest first)
|
|
74
|
+
filteredWorkflows.sort((a, b) => new Date(b.metadata?.updatedAt || 0).getTime() -
|
|
75
|
+
new Date(a.metadata?.updatedAt || 0).getTime());
|
|
76
|
+
// Apply pagination
|
|
77
|
+
const offset = options?.offset || 0;
|
|
78
|
+
const limit = options?.limit || filteredWorkflows.length;
|
|
79
|
+
return filteredWorkflows.slice(offset, offset + limit);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Delete a workflow
|
|
83
|
+
*/
|
|
84
|
+
export async function deleteWorkflow(id) {
|
|
85
|
+
return workflows.delete(id);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get workflow count
|
|
89
|
+
*/
|
|
90
|
+
export async function getWorkflowCount() {
|
|
91
|
+
return workflows.size;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Initialize with sample workflows (for development)
|
|
95
|
+
*/
|
|
96
|
+
export async function initializeSampleWorkflows() {
|
|
97
|
+
// Only initialize if no workflows exist
|
|
98
|
+
if (workflows.size > 0) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
// Add a sample workflow
|
|
102
|
+
const sampleWorkflow = {
|
|
103
|
+
name: "Sample Chat Workflow",
|
|
104
|
+
description: "A simple workflow demonstrating chat completion",
|
|
105
|
+
nodes: [],
|
|
106
|
+
edges: [],
|
|
107
|
+
metadata: {
|
|
108
|
+
version: "1.0.0",
|
|
109
|
+
createdAt: new Date().toISOString(),
|
|
110
|
+
updatedAt: new Date().toISOString(),
|
|
111
|
+
author: "System",
|
|
112
|
+
tags: ["sample", "chat"]
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
await saveWorkflow(sampleWorkflow);
|
|
116
|
+
}
|