@d34dman/flowdrop 0.0.25 → 0.0.27

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 (40) hide show
  1. package/README.md +52 -62
  2. package/dist/components/App.svelte +12 -2
  3. package/dist/components/ConfigForm.svelte +500 -9
  4. package/dist/components/ConfigForm.svelte.d.ts +2 -0
  5. package/dist/components/ConfigModal.svelte +4 -70
  6. package/dist/components/ConfigPanel.svelte +4 -9
  7. package/dist/components/EdgeRefresher.svelte +41 -0
  8. package/dist/components/EdgeRefresher.svelte.d.ts +9 -0
  9. package/dist/components/ReadOnlyDetails.svelte +3 -1
  10. package/dist/components/UniversalNode.svelte +6 -3
  11. package/dist/components/WorkflowEditor.svelte +30 -0
  12. package/dist/components/WorkflowEditor.svelte.d.ts +3 -1
  13. package/dist/components/form/FormCheckboxGroup.svelte +2 -9
  14. package/dist/components/form/FormField.svelte +1 -12
  15. package/dist/components/form/FormFieldWrapper.svelte +2 -10
  16. package/dist/components/form/FormFieldWrapper.svelte.d.ts +1 -1
  17. package/dist/components/form/FormMarkdownEditor.svelte +0 -2
  18. package/dist/components/form/FormNumberField.svelte +5 -6
  19. package/dist/components/form/FormRangeField.svelte +3 -13
  20. package/dist/components/form/FormSelect.svelte +4 -5
  21. package/dist/components/form/FormSelect.svelte.d.ts +1 -1
  22. package/dist/components/form/FormTextField.svelte +3 -4
  23. package/dist/components/form/FormTextarea.svelte +3 -4
  24. package/dist/components/form/FormToggle.svelte +2 -3
  25. package/dist/components/form/index.d.ts +14 -14
  26. package/dist/components/form/index.js +14 -14
  27. package/dist/components/form/types.d.ts +2 -2
  28. package/dist/components/form/types.js +1 -1
  29. package/dist/components/nodes/NotesNode.svelte +39 -45
  30. package/dist/components/nodes/NotesNode.svelte.d.ts +1 -1
  31. package/dist/components/nodes/SimpleNode.svelte +92 -142
  32. package/dist/components/nodes/SquareNode.svelte +75 -58
  33. package/dist/components/nodes/WorkflowNode.svelte +1 -3
  34. package/dist/index.d.ts +3 -1
  35. package/dist/index.js +2 -0
  36. package/dist/services/dynamicSchemaService.d.ts +108 -0
  37. package/dist/services/dynamicSchemaService.js +445 -0
  38. package/dist/styles/base.css +1 -1
  39. package/dist/types/index.d.ts +213 -0
  40. package/package.json +163 -155
@@ -147,6 +147,190 @@ export type BuiltinNodeType = 'note' | 'simple' | 'square' | 'tool' | 'gateway'
147
147
  * ```
148
148
  */
149
149
  export type NodeType = BuiltinNodeType | (string & Record<never, never>);
150
+ /**
151
+ * HTTP method types for dynamic schema endpoints
152
+ */
153
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH';
154
+ /**
155
+ * Dynamic schema endpoint configuration
156
+ * Used when the config schema needs to be fetched at runtime from a REST endpoint
157
+ *
158
+ * @example
159
+ * ```typescript
160
+ * const schemaEndpoint: DynamicSchemaEndpoint = {
161
+ * url: "/api/nodes/{nodeTypeId}/schema",
162
+ * method: "GET",
163
+ * headers: { "X-Custom-Header": "value" },
164
+ * parameterMapping: {
165
+ * nodeTypeId: "metadata.id",
166
+ * instanceId: "id"
167
+ * }
168
+ * };
169
+ * ```
170
+ */
171
+ export interface DynamicSchemaEndpoint {
172
+ /**
173
+ * The URL to fetch the schema from.
174
+ * Supports template variables in curly braces (e.g., "/api/nodes/{nodeTypeId}/schema")
175
+ * Variables are resolved from node metadata, config, or instance data.
176
+ */
177
+ url: string;
178
+ /**
179
+ * HTTP method to use for fetching the schema.
180
+ * @default "GET"
181
+ */
182
+ method?: HttpMethod;
183
+ /**
184
+ * Custom headers to include in the request
185
+ */
186
+ headers?: Record<string, string>;
187
+ /**
188
+ * Maps template variables to their source paths.
189
+ * Keys are variable names used in the URL, values are dot-notation paths
190
+ * to resolve from the node context (e.g., "metadata.id", "config.apiKey", "id")
191
+ */
192
+ parameterMapping?: Record<string, string>;
193
+ /**
194
+ * Request body for POST/PUT/PATCH methods.
195
+ * Can include template variables like the URL.
196
+ */
197
+ body?: Record<string, unknown>;
198
+ /**
199
+ * Timeout in milliseconds for the schema fetch request
200
+ * @default 10000
201
+ */
202
+ timeout?: number;
203
+ /**
204
+ * Whether to cache the fetched schema per node instance
205
+ * @default true
206
+ */
207
+ cacheSchema?: boolean;
208
+ }
209
+ /**
210
+ * External edit link configuration
211
+ * Used when the node configuration should be handled by an external 3rd party form
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * const editLink: ExternalEditLink = {
216
+ * url: "https://admin.example.com/nodes/{nodeTypeId}/edit/{instanceId}",
217
+ * label: "Configure in Admin Panel",
218
+ * parameterMapping: {
219
+ * nodeTypeId: "metadata.id",
220
+ * instanceId: "id"
221
+ * },
222
+ * openInNewTab: true
223
+ * };
224
+ * ```
225
+ */
226
+ export interface ExternalEditLink {
227
+ /**
228
+ * The URL to the external edit form.
229
+ * Supports template variables in curly braces (e.g., "/admin/nodes/{nodeTypeId}/edit")
230
+ * Variables are resolved from node metadata, config, or instance data.
231
+ */
232
+ url: string;
233
+ /**
234
+ * Display label for the edit link button
235
+ * @default "Configure Externally"
236
+ */
237
+ label?: string;
238
+ /**
239
+ * Icon to display alongside the label (Iconify icon name)
240
+ * @default "heroicons:arrow-top-right-on-square"
241
+ */
242
+ icon?: string;
243
+ /**
244
+ * Maps template variables to their source paths.
245
+ * Keys are variable names used in the URL, values are dot-notation paths
246
+ * to resolve from the node context (e.g., "metadata.id", "config.apiKey", "id")
247
+ */
248
+ parameterMapping?: Record<string, string>;
249
+ /**
250
+ * Whether to open the link in a new tab
251
+ * @default true
252
+ */
253
+ openInNewTab?: boolean;
254
+ /**
255
+ * Optional tooltip/description for the link
256
+ */
257
+ description?: string;
258
+ /**
259
+ * Callback URL parameter name for FlowDrop to receive updates
260
+ * If set, the external form should redirect back with config updates
261
+ */
262
+ callbackUrlParam?: string;
263
+ }
264
+ /**
265
+ * Admin/Edit configuration for nodes with dynamic or external configuration
266
+ * Used when the config schema cannot be determined at workflow load time
267
+ * or when configuration is handled by a 3rd party system.
268
+ *
269
+ * @example
270
+ * ```typescript
271
+ * // Option 1: External edit link only (opens external form in new tab)
272
+ * const configEdit: ConfigEditOptions = {
273
+ * externalEditLink: {
274
+ * url: "https://admin.example.com/configure/{nodeId}",
275
+ * label: "Open Configuration Portal"
276
+ * }
277
+ * };
278
+ *
279
+ * // Option 2: Dynamic schema (fetches schema from REST endpoint)
280
+ * const configEdit: ConfigEditOptions = {
281
+ * dynamicSchema: {
282
+ * url: "/api/nodes/{nodeTypeId}/schema",
283
+ * method: "GET"
284
+ * }
285
+ * };
286
+ *
287
+ * // Option 3: Both (user can choose)
288
+ * const configEdit: ConfigEditOptions = {
289
+ * externalEditLink: {
290
+ * url: "https://admin.example.com/configure/{nodeId}",
291
+ * label: "Advanced Configuration"
292
+ * },
293
+ * dynamicSchema: {
294
+ * url: "/api/nodes/{nodeTypeId}/schema"
295
+ * },
296
+ * preferDynamicSchema: true
297
+ * };
298
+ * ```
299
+ */
300
+ export interface ConfigEditOptions {
301
+ /**
302
+ * External link configuration for 3rd party form
303
+ * When configured, shows a link/button to open external configuration
304
+ */
305
+ externalEditLink?: ExternalEditLink;
306
+ /**
307
+ * Dynamic schema endpoint configuration
308
+ * When configured, fetches the config schema from the specified endpoint
309
+ */
310
+ dynamicSchema?: DynamicSchemaEndpoint;
311
+ /**
312
+ * When both externalEditLink and dynamicSchema are configured,
313
+ * determines which to use by default
314
+ * @default false (prefer external link)
315
+ */
316
+ preferDynamicSchema?: boolean;
317
+ /**
318
+ * Show a "Refresh Schema" button when using dynamic schema
319
+ * Allows users to manually refresh the schema
320
+ * @default true
321
+ */
322
+ showRefreshButton?: boolean;
323
+ /**
324
+ * Message to display when schema is being loaded
325
+ * @default "Loading configuration options..."
326
+ */
327
+ loadingMessage?: string;
328
+ /**
329
+ * Message to display when schema fetch fails
330
+ * @default "Failed to load configuration. Use external editor instead."
331
+ */
332
+ errorMessage?: string;
333
+ }
150
334
  /**
151
335
  * UI-related extension settings for nodes
152
336
  * Used to control visual behavior in the workflow editor
@@ -183,6 +367,11 @@ export interface NodeExtensions {
183
367
  * Used to control visual behavior in the workflow editor
184
368
  */
185
369
  ui?: NodeUIExtensions;
370
+ /**
371
+ * Per-instance admin/edit configuration override
372
+ * Allows overriding the node type's configEdit settings for specific instances
373
+ */
374
+ configEdit?: ConfigEditOptions;
186
375
  /**
187
376
  * Namespaced extension data from 3rd party integrations
188
377
  * Use your package/organization name as the key (e.g., "myapp", "acme:analyzer")
@@ -214,6 +403,30 @@ export interface NodeMetadata {
214
403
  /** Default configuration values for this node type */
215
404
  config?: Record<string, unknown>;
216
405
  tags?: string[];
406
+ /**
407
+ * Admin/Edit configuration for nodes with dynamic or external configuration.
408
+ * Used when the config schema cannot be determined at workflow load time
409
+ * or when configuration is handled by a 3rd party system.
410
+ *
411
+ * Supports two options:
412
+ * 1. External edit link - Opens a 3rd party form in a new tab
413
+ * 2. Dynamic schema - Fetches the config schema from a REST endpoint
414
+ *
415
+ * @example
416
+ * ```typescript
417
+ * configEdit: {
418
+ * externalEditLink: {
419
+ * url: "https://admin.example.com/nodes/{nodeTypeId}/configure",
420
+ * label: "Configure in Admin Portal"
421
+ * },
422
+ * dynamicSchema: {
423
+ * url: "/api/nodes/{nodeTypeId}/schema",
424
+ * method: "GET"
425
+ * }
426
+ * }
427
+ * ```
428
+ */
429
+ configEdit?: ConfigEditOptions;
217
430
  /**
218
431
  * Custom extension properties for 3rd party integrations
219
432
  * Allows storing additional configuration and UI state data at the node type level
package/package.json CHANGED
@@ -1,156 +1,164 @@
1
1
  {
2
- "name": "@d34dman/flowdrop",
3
- "license": "MIT",
4
- "private": false,
5
- "version": "0.0.25",
6
- "scripts": {
7
- "dev": "vite dev",
8
- "build": "vite build && npm run prepack",
9
- "build:drupal": "vite build --config vite.config.drupal.ts",
10
- "build:production": "vite build --config vite.config.production.ts",
11
- "watch:build:drupal": "npm-watch build:drupal",
12
- "watch:build:production": "npm-watch build:production",
13
- "watch:build": "npm-watch build",
14
- "preview": "vite preview",
15
- "prepare": "svelte-kit sync || echo ''",
16
- "prepack": "svelte-kit sync && svelte-package && publint",
17
- "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
18
- "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
19
- "lint": "eslint . && prettier --check .",
20
- "test:unit": "vitest",
21
- "test": "npm run test:unit -- --run && npm run test:e2e",
22
- "test:e2e": "playwright test",
23
- "format": "prettier --write .",
24
- "storybook": "storybook dev -p 6006",
25
- "build-storybook": "storybook build"
26
- },
27
- "watch": {
28
- "build": {
29
- "ignore": "build",
30
- "patterns": [
31
- "src"
32
- ],
33
- "extensions": "js,ts,svelte,html,css,svg",
34
- "quiet": true,
35
- "legacyWatch": true,
36
- "delay": 2500,
37
- "runOnChangeOnly": false
38
- },
39
- "build:drupal": {
40
- "ignore": "build",
41
- "patterns": [
42
- "src"
43
- ],
44
- "extensions": "js,ts,svelte,html,css,svg",
45
- "quiet": true,
46
- "legacyWatch": true,
47
- "delay": 2500,
48
- "runOnChangeOnly": false
49
- },
50
- "build:production": {
51
- "ignore": "build",
52
- "patterns": [
53
- "src"
54
- ],
55
- "extensions": "js,ts,svelte,html,css,svg",
56
- "quiet": true,
57
- "legacyWatch": true,
58
- "delay": 2500,
59
- "runOnChangeOnly": false
60
- }
61
- },
62
- "files": [
63
- "dist",
64
- "!dist/**/*.test.*",
65
- "!dist/**/*.spec.*"
66
- ],
67
- "sideEffects": [
68
- "**/*.css",
69
- "./dist/styles/base.css"
70
- ],
71
- "svelte": "./dist/index.js",
72
- "types": "./dist/index.d.ts",
73
- "type": "module",
74
- "exports": {
75
- ".": {
76
- "types": "./dist/index.d.ts",
77
- "svelte": "./dist/index.js",
78
- "default": "./dist/index.js"
79
- },
80
- "./styles/base.css": "./dist/styles/base.css"
81
- },
82
- "peerDependencies": {
83
- "@sveltejs/kit": "^2.0.0",
84
- "svelte": "^5.0.0"
85
- },
86
- "repository": {
87
- "type": "git",
88
- "url": "git+https://github.com/d34dman/flowdrop.git"
89
- },
90
- "devDependencies": {
91
- "@chromatic-com/storybook": "^4.0.1",
92
- "@eslint/compat": "^1.2.5",
93
- "@eslint/js": "^9.18.0",
94
- "@iconify/svelte": "^5.0.0",
95
- "@playwright/test": "^1.49.1",
96
- "@storybook/addon-docs": "^9.0.15",
97
- "@storybook/addon-svelte-csf": "^5.0.4",
98
- "@storybook/addon-vitest": "^9.0.15",
99
- "@storybook/sveltekit": "^9.0.15",
100
- "@sveltejs/adapter-auto": "^6.0.0",
101
- "@sveltejs/adapter-node": "^5.4.0",
102
- "@sveltejs/kit": "^2.49.2",
103
- "@sveltejs/package": "^2.0.0",
104
- "@sveltejs/vite-plugin-svelte": "^5.0.0",
105
- "@types/marked": "^6.0.0",
106
- "@types/node": "^20",
107
- "@types/uuid": "^10.0.0",
108
- "@vitest/browser": "^3.2.3",
109
- "eslint": "^9.18.0",
110
- "eslint-config-prettier": "^10.0.1",
111
- "eslint-plugin-storybook": "^9.0.15",
112
- "eslint-plugin-svelte": "^3.0.0",
113
- "globals": "^16.0.0",
114
- "msw": "^2.12.7",
115
- "npm-watch": "^0.13.0",
116
- "playwright": "^1.53.0",
117
- "prettier": "^3.4.2",
118
- "prettier-plugin-svelte": "^3.3.3",
119
- "publint": "^0.3.2",
120
- "storybook": "^9.0.15",
121
- "svelte": "^5.0.0",
122
- "svelte-check": "^4.0.0",
123
- "terser": "^5.43.1",
124
- "typescript": "^5.0.0",
125
- "typescript-eslint": "^8.20.0",
126
- "vite": "^6.2.6",
127
- "vite-plugin-devtools-json": "^0.2.1",
128
- "vitest": "^3.2.3",
129
- "vitest-browser-svelte": "^0.1.0"
130
- },
131
- "overrides": {
132
- "@sveltejs/kit": {
133
- "cookie": "0.7.2"
134
- }
135
- },
136
- "keywords": [
137
- "svelte"
138
- ],
139
- "dependencies": {
140
- "@codemirror/autocomplete": "^6.20.0",
141
- "@codemirror/lang-json": "^6.0.2",
142
- "@codemirror/lint": "^6.9.2",
143
- "@codemirror/theme-one-dark": "^6.1.3",
144
- "@xyflow/svelte": "~1.2",
145
- "codemirror": "^6.0.2",
146
- "easymde": "^2.20.0",
147
- "marked": "^16.1.1",
148
- "svelte-5-french-toast": "^2.0.6",
149
- "uuid": "^11.1.0"
150
- },
151
- "msw": {
152
- "workerDirectory": [
153
- "static"
154
- ]
155
- }
156
- }
2
+ "name": "@d34dman/flowdrop",
3
+ "license": "MIT",
4
+ "private": false,
5
+ "version": "0.0.27",
6
+ "scripts": {
7
+ "dev": "vite dev",
8
+ "build": "vite build && npm run prepack",
9
+ "build:drupal": "vite build --config vite.config.drupal.ts",
10
+ "build:production": "vite build --config vite.config.production.ts",
11
+ "watch:build:drupal": "npm-watch build:drupal",
12
+ "watch:build:production": "npm-watch build:production",
13
+ "watch:build": "npm-watch build",
14
+ "preview": "vite preview",
15
+ "prepare": "svelte-kit sync || echo ''",
16
+ "prepack": "svelte-kit sync && svelte-package && publint",
17
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
18
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
19
+ "lint": "eslint . && prettier --check .",
20
+ "test": "vitest run",
21
+ "test:watch": "vitest",
22
+ "test:ui": "vitest --ui",
23
+ "test:coverage": "vitest run --coverage",
24
+ "test:e2e": "playwright test",
25
+ "test:e2e:ui": "playwright test --ui",
26
+ "test:e2e:debug": "playwright test --debug",
27
+ "test:all": "npm run test && npm run test:e2e",
28
+ "format": "prettier --write .",
29
+ "storybook": "storybook dev -p 6006",
30
+ "build-storybook": "storybook build"
31
+ },
32
+ "watch": {
33
+ "build": {
34
+ "ignore": "build",
35
+ "patterns": [
36
+ "src"
37
+ ],
38
+ "extensions": "js,ts,svelte,html,css,svg",
39
+ "quiet": true,
40
+ "legacyWatch": true,
41
+ "delay": 2500,
42
+ "runOnChangeOnly": false
43
+ },
44
+ "build:drupal": {
45
+ "ignore": "build",
46
+ "patterns": [
47
+ "src"
48
+ ],
49
+ "extensions": "js,ts,svelte,html,css,svg",
50
+ "quiet": true,
51
+ "legacyWatch": true,
52
+ "delay": 2500,
53
+ "runOnChangeOnly": false
54
+ },
55
+ "build:production": {
56
+ "ignore": "build",
57
+ "patterns": [
58
+ "src"
59
+ ],
60
+ "extensions": "js,ts,svelte,html,css,svg",
61
+ "quiet": true,
62
+ "legacyWatch": true,
63
+ "delay": 2500,
64
+ "runOnChangeOnly": false
65
+ }
66
+ },
67
+ "files": [
68
+ "dist",
69
+ "!dist/**/*.test.*",
70
+ "!dist/**/*.spec.*"
71
+ ],
72
+ "sideEffects": [
73
+ "**/*.css",
74
+ "./dist/styles/base.css"
75
+ ],
76
+ "svelte": "./dist/index.js",
77
+ "types": "./dist/index.d.ts",
78
+ "type": "module",
79
+ "exports": {
80
+ ".": {
81
+ "types": "./dist/index.d.ts",
82
+ "svelte": "./dist/index.js",
83
+ "default": "./dist/index.js"
84
+ },
85
+ "./styles/base.css": "./dist/styles/base.css"
86
+ },
87
+ "peerDependencies": {
88
+ "@sveltejs/kit": "^2.0.0",
89
+ "svelte": "^5.0.0"
90
+ },
91
+ "repository": {
92
+ "type": "git",
93
+ "url": "git+https://github.com/d34dman/flowdrop.git"
94
+ },
95
+ "devDependencies": {
96
+ "@chromatic-com/storybook": "^4.0.1",
97
+ "@eslint/compat": "^1.2.5",
98
+ "@eslint/js": "^9.18.0",
99
+ "@iconify/svelte": "^5.0.0",
100
+ "@playwright/test": "^1.49.1",
101
+ "@storybook/addon-docs": "^9.0.15",
102
+ "@storybook/addon-svelte-csf": "^5.0.4",
103
+ "@storybook/addon-vitest": "^9.0.15",
104
+ "@storybook/sveltekit": "^9.0.15",
105
+ "@sveltejs/adapter-auto": "^6.0.0",
106
+ "@sveltejs/adapter-node": "^5.4.0",
107
+ "@sveltejs/kit": "^2.49.2",
108
+ "@sveltejs/package": "^2.0.0",
109
+ "@sveltejs/vite-plugin-svelte": "^5.0.0",
110
+ "@types/marked": "^6.0.0",
111
+ "@types/node": "^20",
112
+ "@types/uuid": "^10.0.0",
113
+ "@vitest/browser": "^3.2.3",
114
+ "@vitest/coverage-v8": "^3.2.4",
115
+ "@vitest/ui": "^3.2.4",
116
+ "eslint": "^9.18.0",
117
+ "eslint-config-prettier": "^10.0.1",
118
+ "eslint-plugin-storybook": "^9.0.15",
119
+ "eslint-plugin-svelte": "^3.0.0",
120
+ "globals": "^16.0.0",
121
+ "happy-dom": "^20.0.11",
122
+ "msw": "^2.12.7",
123
+ "npm-watch": "^0.13.0",
124
+ "playwright": "^1.53.0",
125
+ "prettier": "^3.4.2",
126
+ "prettier-plugin-svelte": "^3.3.3",
127
+ "publint": "^0.3.2",
128
+ "storybook": "^9.0.15",
129
+ "svelte": "^5.0.0",
130
+ "svelte-check": "^4.0.0",
131
+ "terser": "^5.43.1",
132
+ "typescript": "^5.0.0",
133
+ "typescript-eslint": "^8.20.0",
134
+ "vite": "^6.2.6",
135
+ "vite-plugin-devtools-json": "^0.2.1",
136
+ "vitest": "^3.2.3",
137
+ "vitest-browser-svelte": "^0.1.0"
138
+ },
139
+ "overrides": {
140
+ "@sveltejs/kit": {
141
+ "cookie": "0.7.2"
142
+ }
143
+ },
144
+ "keywords": [
145
+ "svelte"
146
+ ],
147
+ "dependencies": {
148
+ "@codemirror/autocomplete": "^6.20.0",
149
+ "@codemirror/lang-json": "^6.0.2",
150
+ "@codemirror/lint": "^6.9.2",
151
+ "@codemirror/theme-one-dark": "^6.1.3",
152
+ "@xyflow/svelte": "~1.2",
153
+ "codemirror": "^6.0.2",
154
+ "easymde": "^2.20.0",
155
+ "marked": "^16.1.1",
156
+ "svelte-5-french-toast": "^2.0.6",
157
+ "uuid": "^11.1.0"
158
+ },
159
+ "msw": {
160
+ "workerDirectory": [
161
+ "static"
162
+ ]
163
+ }
164
+ }