@d34dman/flowdrop 0.0.57 → 0.0.59

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 (54) hide show
  1. package/README.md +9 -8
  2. package/dist/adapters/WorkflowAdapter.d.ts +2 -1
  3. package/dist/adapters/agentspec/AgentSpecAdapter.d.ts +4 -0
  4. package/dist/adapters/agentspec/AgentSpecAdapter.js +27 -22
  5. package/dist/adapters/agentspec/componentTypeDefaults.d.ts +73 -0
  6. package/dist/adapters/agentspec/componentTypeDefaults.js +238 -0
  7. package/dist/adapters/agentspec/{nodeTypeRegistry.d.ts → defaultNodeTypes.d.ts} +21 -30
  8. package/dist/adapters/agentspec/{nodeTypeRegistry.js → defaultNodeTypes.js} +31 -59
  9. package/dist/adapters/agentspec/index.d.ts +3 -1
  10. package/dist/adapters/agentspec/index.js +4 -2
  11. package/dist/components/App.svelte +57 -13
  12. package/dist/components/NodeSidebar.svelte +20 -8
  13. package/dist/components/NodeSidebar.svelte.d.ts +2 -1
  14. package/dist/components/WorkflowEditor.svelte +14 -13
  15. package/dist/components/form/FormMarkdownEditor.svelte +546 -422
  16. package/dist/components/form/FormMarkdownEditor.svelte.d.ts +2 -0
  17. package/dist/components/form/FormUISchemaRenderer.svelte +4 -8
  18. package/dist/components/form/types.d.ts +1 -1
  19. package/dist/components/nodes/WorkflowNode.svelte +1 -2
  20. package/dist/core/index.d.ts +13 -3
  21. package/dist/core/index.js +16 -3
  22. package/dist/form/code.js +6 -1
  23. package/dist/form/fieldRegistry.d.ts +79 -15
  24. package/dist/form/fieldRegistry.js +104 -49
  25. package/dist/form/full.d.ts +2 -2
  26. package/dist/form/full.js +2 -2
  27. package/dist/form/index.d.ts +3 -3
  28. package/dist/form/index.js +6 -2
  29. package/dist/form/markdown.d.ts +3 -3
  30. package/dist/form/markdown.js +8 -4
  31. package/dist/index.d.ts +2 -2
  32. package/dist/index.js +2 -2
  33. package/dist/registry/BaseRegistry.d.ts +92 -0
  34. package/dist/registry/BaseRegistry.js +124 -0
  35. package/dist/registry/builtinFormats.d.ts +23 -0
  36. package/dist/registry/builtinFormats.js +70 -0
  37. package/dist/registry/builtinNodes.js +4 -0
  38. package/dist/registry/index.d.ts +2 -1
  39. package/dist/registry/index.js +2 -0
  40. package/dist/registry/nodeComponentRegistry.d.ts +26 -57
  41. package/dist/registry/nodeComponentRegistry.js +29 -82
  42. package/dist/registry/workflowFormatRegistry.d.ts +122 -0
  43. package/dist/registry/workflowFormatRegistry.js +96 -0
  44. package/dist/schema/index.d.ts +23 -0
  45. package/dist/schema/index.js +23 -0
  46. package/dist/schemas/v1/workflow.schema.json +1078 -0
  47. package/dist/stores/portCoordinateStore.js +1 -4
  48. package/dist/stores/workflowStore.d.ts +3 -0
  49. package/dist/stores/workflowStore.js +3 -0
  50. package/dist/svelte-app.d.ts +4 -0
  51. package/dist/svelte-app.js +9 -1
  52. package/dist/types/index.d.ts +18 -0
  53. package/dist/types/index.js +4 -0
  54. package/package.json +20 -13
@@ -8,10 +8,13 @@
8
8
  * - External libraries to contribute node types via plugins
9
9
  * - Runtime switching between different node visualizations
10
10
  */
11
+ import { BaseRegistry } from './BaseRegistry.js';
11
12
  /**
12
13
  * Central registry for node component types.
13
14
  * Allows built-in and third-party components to be registered and resolved.
14
15
  *
16
+ * Extends BaseRegistry for shared mechanics (subscribe, onClear, etc.).
17
+ *
15
18
  * @example
16
19
  * ```typescript
17
20
  * // Register a custom node
@@ -27,13 +30,11 @@
27
30
  * const component = nodeComponentRegistry.getComponent("myCustomNode");
28
31
  * ```
29
32
  */
30
- class NodeComponentRegistry {
31
- /** Map of type -> registration */
32
- components = new Map();
33
+ class NodeComponentRegistry extends BaseRegistry {
33
34
  /** Default type to use when requested type is not found */
34
35
  defaultType = 'workflowNode';
35
- /** Listeners for registry changes */
36
- listeners = new Set();
36
+ /** Initial default type, restored on clear() */
37
+ static INITIAL_DEFAULT_TYPE = 'workflowNode';
37
38
  /**
38
39
  * Register a node component type.
39
40
  *
@@ -51,12 +52,19 @@ class NodeComponentRegistry {
51
52
  * });
52
53
  * ```
53
54
  */
55
+ /**
56
+ * Clear all registrations and reset default type.
57
+ */
58
+ clear() {
59
+ super.clear();
60
+ this.defaultType = NodeComponentRegistry.INITIAL_DEFAULT_TYPE;
61
+ }
54
62
  register(registration, overwrite = false) {
55
- if (this.components.has(registration.type) && !overwrite) {
63
+ if (this.items.has(registration.type) && !overwrite) {
56
64
  throw new Error(`Node type "${registration.type}" is already registered. ` +
57
65
  `Use overwrite: true to replace it, or use a namespaced type like "mylib:${registration.type}".`);
58
66
  }
59
- this.components.set(registration.type, registration);
67
+ this.items.set(registration.type, registration);
60
68
  this.notifyListeners();
61
69
  }
62
70
  /**
@@ -71,28 +79,6 @@ class NodeComponentRegistry {
71
79
  this.register(registration, overwrite);
72
80
  }
73
81
  }
74
- /**
75
- * Unregister a node component type.
76
- *
77
- * @param type - The type identifier to remove
78
- * @returns true if the type was found and removed, false otherwise
79
- */
80
- unregister(type) {
81
- const result = this.components.delete(type);
82
- if (result) {
83
- this.notifyListeners();
84
- }
85
- return result;
86
- }
87
- /**
88
- * Get a registration by type.
89
- *
90
- * @param type - The type identifier to look up
91
- * @returns The registration if found, undefined otherwise
92
- */
93
- get(type) {
94
- return this.components.get(type);
95
- }
96
82
  /**
97
83
  * Get the component for a type, with fallback to default.
98
84
  *
@@ -100,17 +86,21 @@ class NodeComponentRegistry {
100
86
  * @returns The component if found, or the default component
101
87
  */
102
88
  getComponent(type) {
103
- const registration = this.components.get(type) ?? this.components.get(this.defaultType);
89
+ const registration = this.items.get(type) ?? this.items.get(this.defaultType);
104
90
  return registration?.component;
105
91
  }
106
92
  /**
107
- * Check if a type is registered.
93
+ * Get framework-agnostic metadata for a type, without the Svelte component.
108
94
  *
109
- * @param type - The type identifier to check
110
- * @returns true if the type is registered
95
+ * @param type - The type identifier to look up
96
+ * @returns The metadata if found, undefined otherwise
111
97
  */
112
- has(type) {
113
- return this.components.has(type);
98
+ getMetadata(type) {
99
+ const reg = this.items.get(type);
100
+ if (!reg)
101
+ return undefined;
102
+ const { component: _, ...metadata } = reg;
103
+ return metadata;
114
104
  }
115
105
  /**
116
106
  * Get all registered type identifiers.
@@ -118,15 +108,7 @@ class NodeComponentRegistry {
118
108
  * @returns Array of registered type strings
119
109
  */
120
110
  getTypes() {
121
- return Array.from(this.components.keys());
122
- }
123
- /**
124
- * Get all registrations.
125
- *
126
- * @returns Array of all registered node component metadata
127
- */
128
- getAll() {
129
- return Array.from(this.components.values());
111
+ return this.getKeys();
130
112
  }
131
113
  /**
132
114
  * Get registrations filtered by criteria.
@@ -182,7 +164,7 @@ class NodeComponentRegistry {
182
164
  * @throws Error if the type is not registered
183
165
  */
184
166
  setDefaultType(type) {
185
- if (!this.components.has(type)) {
167
+ if (!this.items.has(type)) {
186
168
  throw new Error(`Cannot set default to unregistered type: ${type}`);
187
169
  }
188
170
  this.defaultType = type;
@@ -195,25 +177,6 @@ class NodeComponentRegistry {
195
177
  getDefaultType() {
196
178
  return this.defaultType;
197
179
  }
198
- /**
199
- * Subscribe to registry changes.
200
- * Called whenever components are registered or unregistered.
201
- *
202
- * @param listener - Callback to invoke on changes
203
- * @returns Unsubscribe function
204
- */
205
- subscribe(listener) {
206
- this.listeners.add(listener);
207
- return () => this.listeners.delete(listener);
208
- }
209
- /**
210
- * Notify all listeners of a change.
211
- */
212
- notifyListeners() {
213
- for (const listener of this.listeners) {
214
- listener();
215
- }
216
- }
217
180
  /**
218
181
  * Get oneOf options for config forms.
219
182
  * Returns array suitable for JSON Schema oneOf with const/title.
@@ -241,7 +204,7 @@ class NodeComponentRegistry {
241
204
  * @returns The status position, or default "top-right"
242
205
  */
243
206
  getStatusPosition(type) {
244
- return this.components.get(type)?.statusPosition ?? 'top-right';
207
+ return this.items.get(type)?.statusPosition ?? 'top-right';
245
208
  }
246
209
  /**
247
210
  * Get the status size for a node type.
@@ -250,23 +213,7 @@ class NodeComponentRegistry {
250
213
  * @returns The status size, or default "md"
251
214
  */
252
215
  getStatusSize(type) {
253
- return this.components.get(type)?.statusSize ?? 'md';
254
- }
255
- /**
256
- * Clear all registrations.
257
- * Primarily useful for testing.
258
- */
259
- clear() {
260
- this.components.clear();
261
- this.notifyListeners();
262
- }
263
- /**
264
- * Get the count of registered components.
265
- *
266
- * @returns Number of registered node types
267
- */
268
- get size() {
269
- return this.components.size;
216
+ return this.items.get(type)?.statusSize ?? 'md';
270
217
  }
271
218
  }
272
219
  /** Singleton instance of the node component registry */
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Workflow Format Registry
3
+ *
4
+ * Central registry for workflow format adapters that allows built-in and
5
+ * third-party formats to be registered and resolved at runtime.
6
+ *
7
+ * This enables:
8
+ * - Custom workflow formats (e.g., n8n, LangGraph) to be registered by users
9
+ * - Format adapters to bundle their own node types
10
+ * - Bidirectional conversion between FlowDrop's StandardWorkflow and external formats
11
+ *
12
+ * Extends BaseRegistry for shared mechanics (subscribe, onClear, etc.).
13
+ */
14
+ import type { StandardWorkflow } from '../adapters/WorkflowAdapter.js';
15
+ import type { NodeMetadata, WorkflowFormat } from '../types/index.js';
16
+ import { BaseRegistry } from './BaseRegistry.js';
17
+ /**
18
+ * Validation result returned by format adapters.
19
+ */
20
+ export interface FormatValidationResult {
21
+ valid: boolean;
22
+ errors: string[];
23
+ warnings: string[];
24
+ }
25
+ /**
26
+ * Interface that all workflow format adapters must implement.
27
+ * Adapters handle bidirectional conversion between FlowDrop's StandardWorkflow
28
+ * and an external workflow format.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const myAdapter: WorkflowFormatAdapter = {
33
+ * id: 'n8n',
34
+ * name: 'n8n Workflow',
35
+ * export: (workflow) => JSON.stringify(convertToN8n(workflow)),
36
+ * import: (data) => convertFromN8n(JSON.parse(data)),
37
+ * };
38
+ * ```
39
+ */
40
+ export interface WorkflowFormatAdapter {
41
+ /** Unique format identifier (e.g., 'agentspec', 'n8n') */
42
+ id: WorkflowFormat;
43
+ /** Display name for UI (e.g., 'Agent Spec (Oracle)') */
44
+ name: string;
45
+ /** Description */
46
+ description?: string;
47
+ /** Version */
48
+ version?: string;
49
+ /**
50
+ * Optional node types specific to this format.
51
+ * When provided, these nodes are merged into the sidebar
52
+ * and automatically tagged with this format.
53
+ */
54
+ nodes?: NodeMetadata[];
55
+ /** Convert a StandardWorkflow to this format's JSON string */
56
+ export(workflow: StandardWorkflow): string;
57
+ /** Parse this format's input and convert to StandardWorkflow */
58
+ import(data: string): StandardWorkflow;
59
+ /** Validate whether a workflow can be exported to this format */
60
+ validate?(workflow: StandardWorkflow): FormatValidationResult;
61
+ }
62
+ /**
63
+ * Central registry for workflow format adapters.
64
+ * Singleton — extends BaseRegistry for shared mechanics.
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * // Register a custom format
69
+ * workflowFormatRegistry.register({
70
+ * id: 'n8n',
71
+ * name: 'n8n Workflow',
72
+ * export: (workflow) => JSON.stringify(convertToN8n(workflow)),
73
+ * import: (data) => convertFromN8n(JSON.parse(data)),
74
+ * });
75
+ *
76
+ * // Get an adapter
77
+ * const adapter = workflowFormatRegistry.get('n8n');
78
+ * ```
79
+ */
80
+ declare class WorkflowFormatRegistry extends BaseRegistry<string, WorkflowFormatAdapter> {
81
+ /**
82
+ * Register a workflow format adapter.
83
+ *
84
+ * @param adapter - The format adapter to register
85
+ * @param overwrite - If true, allows overwriting existing registrations
86
+ * @throws Error if format already registered and overwrite is false
87
+ */
88
+ register(adapter: WorkflowFormatAdapter, overwrite?: boolean): void;
89
+ /**
90
+ * Get all registered format identifiers.
91
+ *
92
+ * @returns Array of format id strings
93
+ */
94
+ getIds(): string[];
95
+ /**
96
+ * Get all node types provided by registered format adapters.
97
+ * Collects `adapter.nodes` from all adapters that provide them.
98
+ *
99
+ * @returns Array of NodeMetadata from all format adapters
100
+ */
101
+ getAllFormatNodes(): NodeMetadata[];
102
+ /**
103
+ * Get node types for a specific format.
104
+ *
105
+ * @param formatId - The format identifier
106
+ * @returns Array of NodeMetadata for the format, or empty array
107
+ */
108
+ getFormatNodes(formatId: WorkflowFormat): NodeMetadata[];
109
+ /**
110
+ * Get oneOf options for config forms.
111
+ * Returns array suitable for JSON Schema oneOf with const/title.
112
+ *
113
+ * @returns Array of oneOf items
114
+ */
115
+ getOneOfOptions(): Array<{
116
+ const: string;
117
+ title: string;
118
+ }>;
119
+ }
120
+ /** Singleton instance of the workflow format registry */
121
+ export declare const workflowFormatRegistry: WorkflowFormatRegistry;
122
+ export {};
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Workflow Format Registry
3
+ *
4
+ * Central registry for workflow format adapters that allows built-in and
5
+ * third-party formats to be registered and resolved at runtime.
6
+ *
7
+ * This enables:
8
+ * - Custom workflow formats (e.g., n8n, LangGraph) to be registered by users
9
+ * - Format adapters to bundle their own node types
10
+ * - Bidirectional conversion between FlowDrop's StandardWorkflow and external formats
11
+ *
12
+ * Extends BaseRegistry for shared mechanics (subscribe, onClear, etc.).
13
+ */
14
+ import { BaseRegistry } from './BaseRegistry.js';
15
+ /**
16
+ * Central registry for workflow format adapters.
17
+ * Singleton — extends BaseRegistry for shared mechanics.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * // Register a custom format
22
+ * workflowFormatRegistry.register({
23
+ * id: 'n8n',
24
+ * name: 'n8n Workflow',
25
+ * export: (workflow) => JSON.stringify(convertToN8n(workflow)),
26
+ * import: (data) => convertFromN8n(JSON.parse(data)),
27
+ * });
28
+ *
29
+ * // Get an adapter
30
+ * const adapter = workflowFormatRegistry.get('n8n');
31
+ * ```
32
+ */
33
+ class WorkflowFormatRegistry extends BaseRegistry {
34
+ /**
35
+ * Register a workflow format adapter.
36
+ *
37
+ * @param adapter - The format adapter to register
38
+ * @param overwrite - If true, allows overwriting existing registrations
39
+ * @throws Error if format already registered and overwrite is false
40
+ */
41
+ register(adapter, overwrite = false) {
42
+ if (this.items.has(adapter.id) && !overwrite) {
43
+ throw new Error(`Workflow format "${adapter.id}" is already registered. ` +
44
+ `Use overwrite: true to replace it.`);
45
+ }
46
+ this.items.set(adapter.id, adapter);
47
+ this.notifyListeners();
48
+ }
49
+ /**
50
+ * Get all registered format identifiers.
51
+ *
52
+ * @returns Array of format id strings
53
+ */
54
+ getIds() {
55
+ return this.getKeys();
56
+ }
57
+ /**
58
+ * Get all node types provided by registered format adapters.
59
+ * Collects `adapter.nodes` from all adapters that provide them.
60
+ *
61
+ * @returns Array of NodeMetadata from all format adapters
62
+ */
63
+ getAllFormatNodes() {
64
+ const allNodes = [];
65
+ for (const adapter of this.items.values()) {
66
+ if (adapter.nodes && adapter.nodes.length > 0) {
67
+ allNodes.push(...adapter.nodes);
68
+ }
69
+ }
70
+ return allNodes;
71
+ }
72
+ /**
73
+ * Get node types for a specific format.
74
+ *
75
+ * @param formatId - The format identifier
76
+ * @returns Array of NodeMetadata for the format, or empty array
77
+ */
78
+ getFormatNodes(formatId) {
79
+ const adapter = this.items.get(formatId);
80
+ return adapter?.nodes ?? [];
81
+ }
82
+ /**
83
+ * Get oneOf options for config forms.
84
+ * Returns array suitable for JSON Schema oneOf with const/title.
85
+ *
86
+ * @returns Array of oneOf items
87
+ */
88
+ getOneOfOptions() {
89
+ return this.getAll().map((adapter) => ({
90
+ const: adapter.id,
91
+ title: adapter.name
92
+ }));
93
+ }
94
+ }
95
+ /** Singleton instance of the workflow format registry */
96
+ export const workflowFormatRegistry = new WorkflowFormatRegistry();
@@ -0,0 +1,23 @@
1
+ /**
2
+ * FlowDrop Workflow JSON Schema
3
+ *
4
+ * Provides the versioned JSON Schema for the FlowDrop workflow document format.
5
+ * The schema is generated from the OpenAPI YAML definitions in `api/components/schemas/`.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { workflowSchema, WORKFLOW_SCHEMA_VERSION } from '@d34dman/flowdrop/core';
10
+ *
11
+ * // Use with any JSON Schema validator (e.g., Ajv)
12
+ * import Ajv from 'ajv/dist/2020';
13
+ * const ajv = new Ajv();
14
+ * const validate = ajv.compile(workflowSchema);
15
+ * const valid = validate(myWorkflow);
16
+ * ```
17
+ *
18
+ * @module schema
19
+ */
20
+ import workflowSchema from '../schemas/v1/workflow.schema.json';
21
+ /** Current workflow schema format version */
22
+ export declare const WORKFLOW_SCHEMA_VERSION = "1.0.0";
23
+ export { workflowSchema };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * FlowDrop Workflow JSON Schema
3
+ *
4
+ * Provides the versioned JSON Schema for the FlowDrop workflow document format.
5
+ * The schema is generated from the OpenAPI YAML definitions in `api/components/schemas/`.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { workflowSchema, WORKFLOW_SCHEMA_VERSION } from '@d34dman/flowdrop/core';
10
+ *
11
+ * // Use with any JSON Schema validator (e.g., Ajv)
12
+ * import Ajv from 'ajv/dist/2020';
13
+ * const ajv = new Ajv();
14
+ * const validate = ajv.compile(workflowSchema);
15
+ * const valid = validate(myWorkflow);
16
+ * ```
17
+ *
18
+ * @module schema
19
+ */
20
+ import workflowSchema from '../schemas/v1/workflow.schema.json';
21
+ /** Current workflow schema format version */
22
+ export const WORKFLOW_SCHEMA_VERSION = '1.0.0';
23
+ export { workflowSchema };