@d34dman/flowdrop 0.0.51 → 0.0.53

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.
Files changed (42) hide show
  1. package/dist/api/client.d.ts +5 -1
  2. package/dist/api/client.js +10 -0
  3. package/dist/components/App.svelte +2 -0
  4. package/dist/components/ConfigForm.svelte +1 -0
  5. package/dist/components/NodeSidebar.svelte +4 -21
  6. package/dist/components/SettingsPanel.svelte +1 -2
  7. package/dist/components/ThemeToggle.svelte +1 -1
  8. package/dist/components/WorkflowEditor.svelte +1 -2
  9. package/dist/components/form/FormAutocomplete.svelte +3 -12
  10. package/dist/components/form/FormField.svelte +1 -1
  11. package/dist/components/form/FormFieldLight.svelte +1 -1
  12. package/dist/components/nodes/TerminalNode.svelte +45 -9
  13. package/dist/components/nodes/TerminalNode.svelte.d.ts +2 -1
  14. package/dist/components/nodes/ToolNode.svelte +17 -11
  15. package/dist/config/defaultCategories.d.ts +7 -0
  16. package/dist/config/defaultCategories.js +126 -0
  17. package/dist/config/endpoints.d.ts +1 -0
  18. package/dist/config/endpoints.js +1 -0
  19. package/dist/core/index.d.ts +3 -3
  20. package/dist/core/index.js +1 -1
  21. package/dist/editor/index.d.ts +1 -0
  22. package/dist/editor/index.js +1 -0
  23. package/dist/services/categoriesApi.d.ts +14 -0
  24. package/dist/services/categoriesApi.js +41 -0
  25. package/dist/settings/index.d.ts +2 -1
  26. package/dist/settings/index.js +2 -1
  27. package/dist/stores/categoriesStore.d.ts +32 -0
  28. package/dist/stores/categoriesStore.js +80 -0
  29. package/dist/stores/settingsStore.d.ts +44 -2
  30. package/dist/stores/settingsStore.js +37 -15
  31. package/dist/svelte-app.d.ts +4 -1
  32. package/dist/svelte-app.js +30 -2
  33. package/dist/types/index.d.ts +38 -3
  34. package/dist/utils/colors.d.ts +5 -2
  35. package/dist/utils/colors.js +7 -3
  36. package/dist/utils/fetchWithAuth.d.ts +25 -0
  37. package/dist/utils/fetchWithAuth.js +34 -0
  38. package/dist/utils/icons.d.ts +7 -3
  39. package/dist/utils/icons.js +11 -6
  40. package/package.json +1 -1
  41. package/dist/stores/themeStore.d.ts +0 -68
  42. package/dist/stores/themeStore.js +0 -213
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * API Client for FlowDrop Workflow Library
3
3
  */
4
- import type { NodeMetadata, Workflow, ExecutionResult, PortConfig } from '../types/index.js';
4
+ import type { NodeMetadata, Workflow, ExecutionResult, PortConfig, CategoryDefinition } from '../types/index.js';
5
5
  /**
6
6
  * HTTP API client for FlowDrop
7
7
  */
@@ -80,6 +80,10 @@ export declare class FlowDropApiClient {
80
80
  * Fetch port configuration
81
81
  */
82
82
  getPortConfig(): Promise<PortConfig>;
83
+ /**
84
+ * Fetch category definitions
85
+ */
86
+ getCategories(): Promise<CategoryDefinition[]>;
83
87
  /**
84
88
  * Fetch pipeline data including job information and status
85
89
  */
@@ -215,6 +215,16 @@ export class FlowDropApiClient {
215
215
  }
216
216
  return response.data;
217
217
  }
218
+ /**
219
+ * Fetch category definitions
220
+ */
221
+ async getCategories() {
222
+ const response = await this.request('/categories');
223
+ if (!response.success || !response.data) {
224
+ throw new Error(response.error || 'Failed to fetch categories');
225
+ }
226
+ return response.data;
227
+ }
218
228
  /**
219
229
  * Fetch pipeline data including job information and status
220
230
  */
@@ -738,6 +738,7 @@
738
738
  onClose={() => (isWorkflowSettingsOpen = false)}
739
739
  >
740
740
  <ConfigForm
741
+ {authProvider}
741
742
  schema={workflowConfigSchema}
742
743
  values={workflowConfigValues}
743
744
  showUIExtensions={false}
@@ -765,6 +766,7 @@
765
766
  onClose={closeConfigSidebar}
766
767
  >
767
768
  <ConfigForm
769
+ {authProvider}
768
770
  node={currentNode}
769
771
  workflowId={$workflowStore?.id}
770
772
  workflowNodes={$workflowStore?.nodes}
@@ -600,6 +600,7 @@
600
600
  ariaDescribedBy="ext-hideUnconnectedHandles-description"
601
601
  onChange={(val) => {
602
602
  uiExtensionValues.hideUnconnectedHandles = val;
603
+ handleFormBlur();
603
604
  }}
604
605
  />
605
606
  </FormFieldWrapper>
@@ -10,6 +10,7 @@
10
10
  import Icon from '@iconify/svelte';
11
11
  import { getNodeIcon, getCategoryIcon } from '../utils/icons.js';
12
12
  import { getCategoryColorToken } from '../utils/colors.js';
13
+ import { getCategoryLabel } from '../stores/categoriesStore.js';
13
14
  import { SvelteSet } from 'svelte/reactivity';
14
15
  import { uiSettings, updateSettings } from '../stores/settingsStore.js';
15
16
 
@@ -142,29 +143,11 @@
142
143
  }
143
144
 
144
145
  /**
145
- * Get category display name
146
+ * Get category display name from the categories store.
147
+ * Falls back to auto-capitalizing the category machine name.
146
148
  */
147
149
  function getCategoryDisplayName(category: NodeCategory): string {
148
- const names: Record<NodeCategory, string> = {
149
- triggers: 'Triggers',
150
- inputs: 'Inputs',
151
- outputs: 'Outputs',
152
- prompts: 'Prompts',
153
- models: 'Models',
154
- processing: 'Processing',
155
- logic: 'Logic',
156
- data: 'Data',
157
- tools: 'Tools',
158
- helpers: 'Helpers',
159
- 'vector stores': 'Vector Stores',
160
- embeddings: 'Embeddings',
161
- memories: 'Memories',
162
- agents: 'Agents',
163
- ai: 'AI',
164
- interrupts: 'Interrupts',
165
- bundles: 'Bundles'
166
- };
167
- return names[category] || category;
150
+ return getCategoryLabel(category);
168
151
  }
169
152
 
170
153
  /**
@@ -144,8 +144,7 @@
144
144
  proximityConnect: {
145
145
  type: 'boolean',
146
146
  title: 'Proximity Connect',
147
- description:
148
- 'Auto-connect compatible ports when dragging nodes near each other',
147
+ description: 'Auto-connect compatible ports when dragging nodes near each other',
149
148
  default: false
150
149
  },
151
150
  proximityConnectDistance: {
@@ -7,7 +7,7 @@
7
7
 
8
8
  <script lang="ts">
9
9
  import Icon from '@iconify/svelte';
10
- import { theme, resolvedTheme, cycleTheme } from '../stores/themeStore.js';
10
+ import { theme, resolvedTheme, cycleTheme } from '../stores/settingsStore.js';
11
11
  import type { ThemePreference } from '../types/settings.js';
12
12
 
13
13
  /**
@@ -16,8 +16,7 @@
16
16
  type ColorMode
17
17
  } from '@xyflow/svelte';
18
18
  import '@xyflow/svelte/dist/style.css';
19
- import { resolvedTheme } from '../stores/themeStore.js';
20
- import { editorSettings, behaviorSettings } from '../stores/settingsStore.js';
19
+ import { resolvedTheme, editorSettings, behaviorSettings } from '../stores/settingsStore.js';
21
20
  import type {
22
21
  WorkflowNode as WorkflowNodeType,
23
22
  NodeMetadata,
@@ -25,6 +25,7 @@
25
25
  import Icon from '@iconify/svelte';
26
26
  import type { AutocompleteConfig, AuthProvider } from '../../types/index.js';
27
27
  import type { FieldOption } from './types.js';
28
+ import { buildFetchHeaders } from '../../utils/fetchWithAuth.js';
28
29
 
29
30
  /**
30
31
  * Props interface for FormAutocomplete component
@@ -192,18 +193,8 @@
192
193
  abortController = new AbortController();
193
194
 
194
195
  try {
195
- // Build headers with authentication
196
- const headers: Record<string, string> = {
197
- Accept: 'application/json',
198
- 'Content-Type': 'application/json'
199
- };
200
-
201
- // Add auth headers if provider is available (call getter to get current value)
202
- const authProvider = getAuthProvider?.();
203
- if (authProvider) {
204
- const authHeaders = await authProvider.getAuthHeaders();
205
- Object.assign(headers, authHeaders);
206
- }
196
+ // Build headers with authentication (call getter to get current value)
197
+ const headers = await buildFetchHeaders(getAuthProvider?.());
207
198
 
208
199
  // Fetch with timeout
209
200
  const timeoutId = setTimeout(() => {
@@ -44,7 +44,7 @@
44
44
  import type { FieldSchema } from './types.js';
45
45
  import { getSchemaOptions } from './types.js';
46
46
  import type { WorkflowNode, WorkflowEdge, AuthProvider } from '../../types/index.js';
47
- import { resolvedTheme } from '../../stores/themeStore.js';
47
+ import { resolvedTheme } from '../../stores/settingsStore.js';
48
48
 
49
49
  interface Props {
50
50
  /** Unique key/id for the field */
@@ -43,7 +43,7 @@
43
43
  import FormCheckboxGroup from './FormCheckboxGroup.svelte';
44
44
  import FormArray from './FormArray.svelte';
45
45
  import { resolveFieldComponent } from '../../form/fieldRegistry.js';
46
- import { resolvedTheme } from '../../stores/themeStore.js';
46
+ import { resolvedTheme } from '../../stores/settingsStore.js';
47
47
  import type { FieldSchema } from './types.js';
48
48
  import { getSchemaOptions } from './types.js';
49
49
 
@@ -10,11 +10,12 @@
10
10
 
11
11
  <script lang="ts">
12
12
  import { Position, Handle } from '@xyflow/svelte';
13
- import type { ConfigValues, NodeMetadata } from '../../types/index.js';
13
+ import type { ConfigValues, NodeMetadata, NodeExtensions, NodePort } from '../../types/index.js';
14
14
  import Icon from '@iconify/svelte';
15
15
  import { getDataTypeColor, getCategoryColorToken } from '../../utils/colors.js';
16
16
  import { getNodeIcon } from '../../utils/icons.js';
17
17
  import { getCircleHandlePosition } from '../../utils/handlePositioning.js';
18
+ import { connectedHandles } from '../../stores/workflowStore.js';
18
19
 
19
20
  /**
20
21
  * Terminal node variant types
@@ -70,6 +71,7 @@
70
71
  config: ConfigValues;
71
72
  metadata: NodeMetadata;
72
73
  nodeId?: string;
74
+ extensions?: NodeExtensions;
73
75
  onConfigOpen?: (node: {
74
76
  id: string;
75
77
  type: string;
@@ -133,6 +135,30 @@
133
135
  */
134
136
  let variantConfig = $derived(VARIANT_CONFIGS[variant]);
135
137
 
138
+ /**
139
+ * Get the hideUnconnectedHandles setting from extensions
140
+ * Merges node type defaults with instance overrides
141
+ */
142
+ const hideUnconnectedHandles = $derived(() => {
143
+ const typeDefault = props.data.metadata?.extensions?.ui?.hideUnconnectedHandles ?? false;
144
+ const instanceOverride = props.data.extensions?.ui?.hideUnconnectedHandles;
145
+ return instanceOverride ?? typeDefault;
146
+ });
147
+
148
+ /**
149
+ * Check if a port should be visible based on connection state and settings
150
+ */
151
+ function isPortVisible(port: NodePort, type: 'input' | 'output'): boolean {
152
+ if (!hideUnconnectedHandles()) {
153
+ return true;
154
+ }
155
+ if (port.required) {
156
+ return true;
157
+ }
158
+ const handleId = `${props.data.nodeId}-${type}-${port.id}`;
159
+ return $connectedHandles.has(handleId);
160
+ }
161
+
136
162
  /**
137
163
  * Get icon using the same resolution as WorkflowNode
138
164
  * Uses getNodeIcon utility with category fallback, or variant default
@@ -239,14 +265,24 @@
239
265
  );
240
266
 
241
267
  /**
242
- * Determine if we should show inputs based on ports
268
+ * Visible input ports filtered by hideUnconnectedHandles setting
269
+ */
270
+ let visibleInputPorts = $derived(inputPorts.filter((port) => isPortVisible(port, 'input')));
271
+
272
+ /**
273
+ * Visible output ports filtered by hideUnconnectedHandles setting
274
+ */
275
+ let visibleOutputPorts = $derived(outputPorts.filter((port) => isPortVisible(port, 'output')));
276
+
277
+ /**
278
+ * Determine if we should show inputs based on visible ports
243
279
  */
244
- let showInputs = $derived(inputPorts.length > 0);
280
+ let showInputs = $derived(visibleInputPorts.length > 0);
245
281
 
246
282
  /**
247
- * Determine if we should show outputs based on ports
283
+ * Determine if we should show outputs based on visible ports
248
284
  */
249
- let showOutputs = $derived(outputPorts.length > 0);
285
+ let showOutputs = $derived(visibleOutputPorts.length > 0);
250
286
 
251
287
  /**
252
288
  * Handle configuration sidebar - using global ConfigSidebar
@@ -317,8 +353,8 @@
317
353
  <div class="flowdrop-terminal-node__circle-wrapper">
318
354
  <!-- Input Handles (for end/exit variants) -->
319
355
  {#if showInputs}
320
- {#each inputPorts as port, index (port.id)}
321
- {@const pos = getCircleHandlePosition(index, inputPorts.length, 'left')}
356
+ {#each visibleInputPorts as port, index (`${port.id}-${visibleInputPorts.length}`)}
357
+ {@const pos = getCircleHandlePosition(index, visibleInputPorts.length, 'left')}
322
358
  <Handle
323
359
  type="target"
324
360
  position={Position.Left}
@@ -339,8 +375,8 @@
339
375
 
340
376
  <!-- Output Handles (for start variant) -->
341
377
  {#if showOutputs}
342
- {#each outputPorts as port, index (port.id)}
343
- {@const pos = getCircleHandlePosition(index, outputPorts.length, 'right')}
378
+ {#each visibleOutputPorts as port, index (`${port.id}-${visibleOutputPorts.length}`)}
379
+ {@const pos = getCircleHandlePosition(index, visibleOutputPorts.length, 'right')}
344
380
  <Handle
345
381
  type="source"
346
382
  position={Position.Right}
@@ -1,10 +1,11 @@
1
- import type { ConfigValues, NodeMetadata } from '../../types/index.js';
1
+ import type { ConfigValues, NodeMetadata, NodeExtensions } from '../../types/index.js';
2
2
  type $$ComponentProps = {
3
3
  data: {
4
4
  label: string;
5
5
  config: ConfigValues;
6
6
  metadata: NodeMetadata;
7
7
  nodeId?: string;
8
+ extensions?: NodeExtensions;
8
9
  onConfigOpen?: (node: {
9
10
  id: string;
10
11
  type: string;
@@ -67,9 +67,7 @@
67
67
  * This allows users to customize the badge text per-instance via config.
68
68
  */
69
69
  const displayBadge = $derived(
70
- (props.data.config?.instanceBadge as string) ||
71
- (props.data.metadata?.badge as string) ||
72
- 'TOOL'
70
+ (props.data.config?.instanceBadge as string) || (props.data.metadata?.badge as string) || 'TOOL'
73
71
  );
74
72
 
75
73
  /**
@@ -96,20 +94,28 @@
96
94
  */
97
95
  let nodeStyle = $derived(`--fd-tool-node-color: ${toolColor}`);
98
96
 
99
- // Check for tool interface ports in metadata
97
+ /**
98
+ * Configurable port dataType to expose on this tool node.
99
+ * Defaults to 'tool', but can be overridden via metadata.portDataType
100
+ * to show a different port type (e.g., 'trigger') when the node is
101
+ * repurposed with a custom badge.
102
+ */
103
+ let portDataType = $derived((props.data.metadata?.portDataType as string) || 'tool');
104
+
105
+ // Check for matching interface ports in metadata
100
106
  let hasToolInputPort = $derived(
101
- props.data.metadata?.inputs?.some((port) => port.dataType === 'tool') || false
107
+ props.data.metadata?.inputs?.some((port) => port.dataType === portDataType) || false
102
108
  );
103
109
  let hasToolOutputPort = $derived(
104
- props.data.metadata?.outputs?.some((port) => port.dataType === 'tool') || false
110
+ props.data.metadata?.outputs?.some((port) => port.dataType === portDataType) || false
105
111
  );
106
112
 
107
- // Get the actual tool ports for proper handle generation
113
+ // Get the actual matching ports for proper handle generation
108
114
  let toolInputPort = $derived(
109
- props.data.metadata?.inputs?.find((port) => port.dataType === 'tool')
115
+ props.data.metadata?.inputs?.find((port) => port.dataType === portDataType)
110
116
  );
111
117
  let toolOutputPort = $derived(
112
- props.data.metadata?.outputs?.find((port) => port.dataType === 'tool')
118
+ props.data.metadata?.outputs?.find((port) => port.dataType === portDataType)
113
119
  );
114
120
 
115
121
  /**
@@ -159,7 +165,7 @@
159
165
  position={Position.Left}
160
166
  id={`${props.data.nodeId}-input-${toolInputPort.id}`}
161
167
  style="top: 40px; transform: translateY(-50%); margin-left: -10px; --fd-handle-fill: {getDataTypeColor(
162
- 'tool'
168
+ portDataType
163
169
  )}; --fd-handle-border-color: var(--fd-handle-border);"
164
170
  />
165
171
  {/if}
@@ -232,7 +238,7 @@
232
238
  position={Position.Right}
233
239
  id={`${props.data.nodeId}-output-${toolOutputPort.id}`}
234
240
  style="top: 40px; transform: translateY(-50%); margin-right: -10px; --fd-handle-fill: {getDataTypeColor(
235
- 'tool'
241
+ portDataType
236
242
  )}; --fd-handle-border-color: var(--fd-handle-border);"
237
243
  />
238
244
  {/if}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Default category definitions for FlowDrop
3
+ * Provides built-in categories with icons, colors, and display labels.
4
+ * These serve as fallbacks when the /categories API endpoint is unavailable.
5
+ */
6
+ import type { CategoryDefinition } from '../types/index.js';
7
+ export declare const DEFAULT_CATEGORIES: CategoryDefinition[];
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Default category definitions for FlowDrop
3
+ * Provides built-in categories with icons, colors, and display labels.
4
+ * These serve as fallbacks when the /categories API endpoint is unavailable.
5
+ */
6
+ export const DEFAULT_CATEGORIES = [
7
+ {
8
+ name: 'triggers',
9
+ label: 'Triggers',
10
+ icon: 'mdi:lightning-bolt',
11
+ color: 'var(--fd-node-cyan)',
12
+ weight: 0
13
+ },
14
+ {
15
+ name: 'inputs',
16
+ label: 'Inputs',
17
+ icon: 'mdi:arrow-down-circle',
18
+ color: 'var(--fd-node-emerald)',
19
+ weight: 1
20
+ },
21
+ {
22
+ name: 'outputs',
23
+ label: 'Outputs',
24
+ icon: 'mdi:arrow-up-circle',
25
+ color: 'var(--fd-node-blue)',
26
+ weight: 2
27
+ },
28
+ {
29
+ name: 'prompts',
30
+ label: 'Prompts',
31
+ icon: 'mdi:message-text',
32
+ color: 'var(--fd-node-amber)',
33
+ weight: 3
34
+ },
35
+ {
36
+ name: 'models',
37
+ label: 'Models',
38
+ icon: 'mdi:robot',
39
+ color: 'var(--fd-node-indigo)',
40
+ weight: 4
41
+ },
42
+ {
43
+ name: 'processing',
44
+ label: 'Processing',
45
+ icon: 'mdi:cog',
46
+ color: 'var(--fd-node-teal)',
47
+ weight: 5
48
+ },
49
+ {
50
+ name: 'logic',
51
+ label: 'Logic',
52
+ icon: 'mdi:source-branch',
53
+ color: 'var(--fd-node-purple)',
54
+ weight: 6
55
+ },
56
+ {
57
+ name: 'data',
58
+ label: 'Data',
59
+ icon: 'mdi:database',
60
+ color: 'var(--fd-node-orange)',
61
+ weight: 7
62
+ },
63
+ {
64
+ name: 'tools',
65
+ label: 'Tools',
66
+ icon: 'mdi:wrench',
67
+ color: 'var(--fd-node-amber)',
68
+ weight: 8
69
+ },
70
+ {
71
+ name: 'helpers',
72
+ label: 'Helpers',
73
+ icon: 'mdi:help-circle',
74
+ color: 'var(--fd-node-slate)',
75
+ weight: 9
76
+ },
77
+ {
78
+ name: 'vector stores',
79
+ label: 'Vector Stores',
80
+ icon: 'mdi:vector-square',
81
+ color: 'var(--fd-node-emerald)',
82
+ weight: 10
83
+ },
84
+ {
85
+ name: 'embeddings',
86
+ label: 'Embeddings',
87
+ icon: 'mdi:vector-polygon',
88
+ color: 'var(--fd-node-indigo)',
89
+ weight: 11
90
+ },
91
+ {
92
+ name: 'memories',
93
+ label: 'Memories',
94
+ icon: 'mdi:brain',
95
+ color: 'var(--fd-node-blue)',
96
+ weight: 12
97
+ },
98
+ {
99
+ name: 'agents',
100
+ label: 'Agents',
101
+ icon: 'mdi:account-cog',
102
+ color: 'var(--fd-node-teal)',
103
+ weight: 13
104
+ },
105
+ {
106
+ name: 'ai',
107
+ label: 'AI',
108
+ icon: 'mdi:shimmer',
109
+ color: 'var(--fd-node-purple)',
110
+ weight: 14
111
+ },
112
+ {
113
+ name: 'interrupts',
114
+ label: 'Interrupts',
115
+ icon: 'mdi:hand-back-left',
116
+ color: 'var(--fd-node-red)',
117
+ weight: 15
118
+ },
119
+ {
120
+ name: 'bundles',
121
+ label: 'Bundles',
122
+ icon: 'mdi:package-variant',
123
+ color: 'var(--fd-node-slate)',
124
+ weight: 16
125
+ }
126
+ ];
@@ -14,6 +14,7 @@ export interface EndpointConfig {
14
14
  metadata: string;
15
15
  };
16
16
  portConfig: string;
17
+ categories: string;
17
18
  workflows: {
18
19
  list: string;
19
20
  get: string;
@@ -15,6 +15,7 @@ export const defaultEndpointConfig = {
15
15
  metadata: '/nodes/{id}/metadata'
16
16
  },
17
17
  portConfig: '/port-config',
18
+ categories: '/categories',
18
19
  workflows: {
19
20
  list: '/workflows',
20
21
  get: '/workflows/{id}',
@@ -14,7 +14,7 @@
14
14
  * import { getStatusColor, createDefaultExecutionInfo } from "@d34dman/flowdrop/core";
15
15
  * ```
16
16
  */
17
- export type { NodeCategory, NodeDataType, NodePort, DynamicPort, Branch, NodeMetadata, NodeExtensions, NodeUIExtensions, ConfigValues, WorkflowNode, WorkflowEdge, Workflow, ApiResponse, NodesResponse, WorkflowResponse, WorkflowsResponse, ExecutionStatus, ExecutionResult, FlowDropConfig, WorkflowEvents, BuiltinNodeType, PortConfig, PortCompatibilityRule, ConfigSchema, ConfigProperty, HttpMethod, DynamicSchemaEndpoint, ExternalEditLink, ConfigEditOptions, EdgeCategory } from '../types/index.js';
17
+ export type { NodeCategory, BuiltinNodeCategory, CategoryDefinition, NodeDataType, NodePort, DynamicPort, Branch, NodeMetadata, NodeExtensions, NodeUIExtensions, ConfigValues, WorkflowNode, WorkflowEdge, Workflow, ApiResponse, NodesResponse, WorkflowResponse, WorkflowsResponse, ExecutionStatus, ExecutionResult, FlowDropConfig, WorkflowEvents, BuiltinNodeType, PortConfig, PortCompatibilityRule, ConfigSchema, ConfigProperty, HttpMethod, DynamicSchemaEndpoint, ExternalEditLink, ConfigEditOptions, EdgeCategory } from '../types/index.js';
18
18
  export type { WorkflowEditorConfig, EditorFeatures, UIConfig, APIConfig, ExecutionConfig, StorageConfig } from '../types/config.js';
19
19
  export type { AuthProvider, StaticAuthConfig, CallbackAuthConfig } from '../types/auth.js';
20
20
  export type { WorkflowChangeType, FlowDropEventHandlers, FlowDropFeatures } from '../types/events.js';
@@ -40,5 +40,5 @@ export { isFieldOptionArray, normalizeOptions } from '../components/form/types.j
40
40
  export { DEFAULT_PORT_CONFIG } from '../config/defaultPortConfig.js';
41
41
  export { defaultEndpointConfig, createEndpointConfig } from '../config/endpoints.js';
42
42
  export * from '../adapters/WorkflowAdapter.js';
43
- export type { ThemePreference, ResolvedTheme } from '../stores/themeStore.js';
44
- export { theme, resolvedTheme, setTheme, toggleTheme, cycleTheme, initializeTheme, isThemeInitialized } from '../stores/themeStore.js';
43
+ export type { ThemePreference, ResolvedTheme } from '../stores/settingsStore.js';
44
+ export { theme, resolvedTheme, setTheme, toggleTheme, cycleTheme, initializeTheme, isThemeInitialized } from '../stores/settingsStore.js';
@@ -51,4 +51,4 @@ export { defaultEndpointConfig, createEndpointConfig } from '../config/endpoints
51
51
  // Adapters
52
52
  // ============================================================================
53
53
  export * from '../adapters/WorkflowAdapter.js';
54
- export { theme, resolvedTheme, setTheme, toggleTheme, cycleTheme, initializeTheme, isThemeInitialized } from '../stores/themeStore.js';
54
+ export { theme, resolvedTheme, setTheme, toggleTheme, cycleTheme, initializeTheme, isThemeInitialized } from '../stores/settingsStore.js';
@@ -74,6 +74,7 @@ export { currentSession, sessions, messages, isExecuting, isLoading, error as pl
74
74
  export { saveWorkflow, updateWorkflow, getWorkflow, getWorkflows, deleteWorkflow, getWorkflowCount, initializeSampleWorkflows } from '../services/workflowStorage.js';
75
75
  export { globalSaveWorkflow, globalExportWorkflow, initializeGlobalSave } from '../services/globalSave.js';
76
76
  export { fetchPortConfig, validatePortConfig } from '../services/portConfigApi.js';
77
+ export { fetchCategories, validateCategories } from '../services/categoriesApi.js';
77
78
  export { fetchDynamicSchema, resolveExternalEditUrl, getEffectiveConfigEditOptions, clearSchemaCache, invalidateSchemaCache, hasConfigEditOptions, shouldShowExternalEdit, shouldUseDynamicSchema } from '../services/dynamicSchemaService.js';
78
79
  export { getDraftStorageKey, saveDraft, loadDraft, deleteDraft, hasDraft, getDraftMetadata, DraftAutoSaveManager } from '../services/draftStorage.js';
79
80
  export { FlowDropApiClient } from '../api/client.js';
@@ -115,6 +115,7 @@ export { currentSession, sessions, messages, isExecuting, isLoading, error as pl
115
115
  export { saveWorkflow, updateWorkflow, getWorkflow, getWorkflows, deleteWorkflow, getWorkflowCount, initializeSampleWorkflows } from '../services/workflowStorage.js';
116
116
  export { globalSaveWorkflow, globalExportWorkflow, initializeGlobalSave } from '../services/globalSave.js';
117
117
  export { fetchPortConfig, validatePortConfig } from '../services/portConfigApi.js';
118
+ export { fetchCategories, validateCategories } from '../services/categoriesApi.js';
118
119
  export { fetchDynamicSchema, resolveExternalEditUrl, getEffectiveConfigEditOptions, clearSchemaCache, invalidateSchemaCache, hasConfigEditOptions, shouldShowExternalEdit, shouldUseDynamicSchema } from '../services/dynamicSchemaService.js';
119
120
  export { getDraftStorageKey, saveDraft, loadDraft, deleteDraft, hasDraft, getDraftMetadata, DraftAutoSaveManager } from '../services/draftStorage.js';
120
121
  // ============================================================================
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Categories API Service
3
+ * Handles fetching category definitions from the backend
4
+ */
5
+ import type { CategoryDefinition } from '../types/index.js';
6
+ import type { EndpointConfig } from '../config/endpoints.js';
7
+ /**
8
+ * Fetch category definitions from API
9
+ */
10
+ export declare function fetchCategories(endpointConfig: EndpointConfig): Promise<CategoryDefinition[]>;
11
+ /**
12
+ * Validate category definitions structure
13
+ */
14
+ export declare function validateCategories(categories: CategoryDefinition[]): boolean;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Categories API Service
3
+ * Handles fetching category definitions from the backend
4
+ */
5
+ import { DEFAULT_CATEGORIES } from '../config/defaultCategories.js';
6
+ import { FlowDropApiClient } from '../api/client.js';
7
+ /**
8
+ * Fetch category definitions from API
9
+ */
10
+ export async function fetchCategories(endpointConfig) {
11
+ try {
12
+ const client = new FlowDropApiClient(endpointConfig.baseUrl);
13
+ const categories = await client.getCategories();
14
+ if (!categories || !Array.isArray(categories)) {
15
+ console.warn('Invalid categories received from API, using default');
16
+ return DEFAULT_CATEGORIES;
17
+ }
18
+ return categories;
19
+ }
20
+ catch (error) {
21
+ console.error('Error fetching categories:', error);
22
+ return DEFAULT_CATEGORIES;
23
+ }
24
+ }
25
+ /**
26
+ * Validate category definitions structure
27
+ */
28
+ export function validateCategories(categories) {
29
+ if (!categories || !Array.isArray(categories)) {
30
+ return false;
31
+ }
32
+ for (const category of categories) {
33
+ if (!category.name || typeof category.name !== 'string') {
34
+ return false;
35
+ }
36
+ if (!category.label || typeof category.label !== 'string') {
37
+ return false;
38
+ }
39
+ }
40
+ return true;
41
+ }
@@ -5,7 +5,8 @@
5
5
  * preferences with hybrid persistence (localStorage + optional API sync).
6
6
  *
7
7
  * Theme stores and functions (theme, resolvedTheme, setTheme, toggleTheme,
8
- * cycleTheme, initializeTheme) are exported from `@d34dman/flowdrop/core`.
8
+ * cycleTheme, initializeTheme) are exported from `@d34dman/flowdrop/core`
9
+ * (sourced from settingsStore).
9
10
  *
10
11
  * @module settings
11
12
  *
@@ -5,7 +5,8 @@
5
5
  * preferences with hybrid persistence (localStorage + optional API sync).
6
6
  *
7
7
  * Theme stores and functions (theme, resolvedTheme, setTheme, toggleTheme,
8
- * cycleTheme, initializeTheme) are exported from `@d34dman/flowdrop/core`.
8
+ * cycleTheme, initializeTheme) are exported from `@d34dman/flowdrop/core`
9
+ * (sourced from settingsStore).
9
10
  *
10
11
  * @module settings
11
12
  *