@flowdrop/flowdrop 1.15.0 → 2.0.0-beta.2

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 (235) hide show
  1. package/CHANGELOG.md +508 -0
  2. package/MIGRATION-2.0.md +629 -0
  3. package/README.md +23 -23
  4. package/dist/adapters/WorkflowAdapter.d.ts +1 -1
  5. package/dist/adapters/WorkflowAdapter.js +14 -8
  6. package/dist/adapters/agentspec/AgentSpecAdapter.js +7 -7
  7. package/dist/api/enhanced-client.js +6 -11
  8. package/dist/chat/batchFeedback.d.ts +39 -0
  9. package/dist/chat/batchFeedback.js +51 -0
  10. package/dist/commands/executor.js +15 -1
  11. package/dist/commands/storeIntegration.svelte.d.ts +4 -1
  12. package/dist/commands/storeIntegration.svelte.js +26 -21
  13. package/dist/commands/types.d.ts +2 -0
  14. package/dist/components/App.svelte +163 -192
  15. package/dist/components/App.svelte.d.ts +47 -8
  16. package/dist/components/ConfigForm.svelte +77 -49
  17. package/dist/components/ConfigModal.svelte +7 -2
  18. package/dist/components/ConnectionLine.svelte +4 -2
  19. package/dist/components/Navbar.svelte +61 -1
  20. package/dist/components/NodeSidebar.svelte +27 -45
  21. package/dist/components/NodeStatusOverlay.svelte +94 -6
  22. package/dist/components/NodeSwapPicker.svelte +10 -8
  23. package/dist/components/PipelineStatus.svelte +22 -68
  24. package/dist/components/PipelineStatus.svelte.d.ts +3 -0
  25. package/dist/components/PortCoordinateTracker.svelte +5 -6
  26. package/dist/components/SchemaForm.stories.svelte +1 -3
  27. package/dist/components/SchemaForm.svelte +22 -27
  28. package/dist/components/SchemaForm.svelte.d.ts +0 -8
  29. package/dist/components/SettingsModal.svelte +8 -3
  30. package/dist/components/SettingsPanel.svelte +20 -4
  31. package/dist/components/SwapMappingEditor.svelte +67 -49
  32. package/dist/components/SwapMappingEditor.svelte.d.ts +0 -2
  33. package/dist/components/UniversalNode.svelte +9 -7
  34. package/dist/components/WorkflowEditor.svelte +121 -111
  35. package/dist/components/WorkflowEditor.svelte.d.ts +21 -10
  36. package/dist/components/chat/AIChatPanel.svelte +98 -89
  37. package/dist/components/chat/AIChatPanel.svelte.d.ts +0 -4
  38. package/dist/components/chat/CommandPreview.svelte +2 -1
  39. package/dist/components/console/CommandConsole.svelte +7 -5
  40. package/dist/components/console/ConsoleAutocomplete.svelte +10 -11
  41. package/dist/components/console/ConsoleAutocomplete.svelte.d.ts +6 -0
  42. package/dist/components/console/ConsoleInput.svelte +15 -6
  43. package/dist/components/console/ConsoleOutput.svelte +2 -1
  44. package/dist/components/form/FormArray.svelte +5 -9
  45. package/dist/components/form/FormArray.svelte.d.ts +2 -1
  46. package/dist/components/form/FormAutocomplete.svelte +16 -15
  47. package/dist/components/form/FormField.svelte +4 -2
  48. package/dist/components/form/FormFieldLight.svelte +34 -3
  49. package/dist/components/form/FormFieldLight.svelte.d.ts +12 -0
  50. package/dist/components/form/FormMarkdownEditor.svelte +9 -4
  51. package/dist/components/form/FormRangeField.svelte +1 -0
  52. package/dist/components/form/FormTemplateEditor.svelte +11 -3
  53. package/dist/components/form/FormToggle.svelte +5 -12
  54. package/dist/components/form/FormToggle.svelte.d.ts +4 -2
  55. package/dist/components/form/FormUISchemaRenderer.svelte +3 -1
  56. package/dist/components/form/templateAutocomplete.js +1 -5
  57. package/dist/components/form/types.d.ts +1 -14
  58. package/dist/components/interrupt/FormPrompt.svelte +3 -2
  59. package/dist/components/interrupt/InterruptBubble.svelte +25 -17
  60. package/dist/components/interrupt/ReviewPrompt.svelte +10 -3
  61. package/dist/components/interrupt/TextInputPrompt.svelte +2 -1
  62. package/dist/components/layouts/MainLayout.svelte +20 -13
  63. package/dist/components/layouts/MainLayout.svelte.d.ts +4 -0
  64. package/dist/components/nodes/AtomNode.svelte +17 -5
  65. package/dist/components/nodes/GatewayNode.svelte +19 -10
  66. package/dist/components/nodes/IdeaNode.svelte +7 -0
  67. package/dist/components/nodes/SimpleNode.svelte +11 -6
  68. package/dist/components/nodes/SquareNode.svelte +15 -8
  69. package/dist/components/nodes/TerminalNode.svelte +9 -4
  70. package/dist/components/nodes/ToolNode.svelte +7 -1
  71. package/dist/components/nodes/WorkflowNode.svelte +16 -7
  72. package/dist/components/playground/ChatInput.svelte +11 -14
  73. package/dist/components/playground/ChatPanel.svelte +6 -49
  74. package/dist/components/playground/ChatPanel.svelte.d.ts +0 -14
  75. package/dist/components/playground/ControlPanel.svelte +134 -123
  76. package/dist/components/playground/ControlPanel.svelte.d.ts +3 -0
  77. package/dist/components/playground/ExecutionLogs.svelte +11 -9
  78. package/dist/components/playground/InputCollector.svelte +11 -9
  79. package/dist/components/playground/MessageStream.svelte +17 -23
  80. package/dist/components/playground/PipelineKanbanView.svelte +69 -8
  81. package/dist/components/playground/PipelineKanbanView.svelte.d.ts +2 -0
  82. package/dist/components/playground/PipelinePanel.svelte +31 -8
  83. package/dist/components/playground/PipelinePanel.svelte.d.ts +2 -0
  84. package/dist/components/playground/PipelineTableView.svelte +188 -44
  85. package/dist/components/playground/PipelineTableView.svelte.d.ts +2 -0
  86. package/dist/components/playground/Playground.svelte +154 -105
  87. package/dist/components/playground/Playground.svelte.d.ts +5 -0
  88. package/dist/components/playground/PlaygroundApp.svelte +11 -1
  89. package/dist/components/playground/PlaygroundApp.svelte.d.ts +6 -0
  90. package/dist/components/playground/PlaygroundModal.svelte +18 -3
  91. package/dist/components/playground/PlaygroundModal.svelte.d.ts +6 -0
  92. package/dist/components/playground/PlaygroundStudio.svelte +40 -32
  93. package/dist/components/playground/PlaygroundStudio.svelte.d.ts +6 -0
  94. package/dist/components/playground/SessionManager.svelte +9 -12
  95. package/dist/components/playground/pipelineViewUtils.svelte.d.ts +30 -1
  96. package/dist/components/playground/pipelineViewUtils.svelte.js +40 -3
  97. package/dist/config/endpoints.d.ts +23 -7
  98. package/dist/config/endpoints.js +30 -10
  99. package/dist/core/index.d.ts +5 -6
  100. package/dist/core/index.js +8 -12
  101. package/dist/display/index.d.ts +6 -3
  102. package/dist/display/index.js +7 -5
  103. package/dist/editor/index.d.ts +20 -21
  104. package/dist/editor/index.js +26 -36
  105. package/dist/form/code.d.ts +25 -15
  106. package/dist/form/code.js +44 -41
  107. package/dist/form/fieldRegistry.d.ts +17 -13
  108. package/dist/form/fieldRegistry.js +32 -12
  109. package/dist/form/full.d.ts +19 -14
  110. package/dist/form/full.js +26 -28
  111. package/dist/form/index.d.ts +3 -4
  112. package/dist/form/index.js +6 -5
  113. package/dist/form/markdown.d.ts +13 -8
  114. package/dist/form/markdown.js +22 -23
  115. package/dist/helpers/proximityConnect.d.ts +3 -2
  116. package/dist/helpers/proximityConnect.js +2 -5
  117. package/dist/helpers/workflowEditorHelper.d.ts +14 -5
  118. package/dist/helpers/workflowEditorHelper.js +28 -25
  119. package/dist/index.d.ts +28 -24
  120. package/dist/index.js +27 -50
  121. package/dist/messages/defaults.d.ts +2 -5
  122. package/dist/messages/defaults.js +3 -6
  123. package/dist/messages/index.d.ts +0 -1
  124. package/dist/messages/index.js +0 -1
  125. package/dist/mocks/app-forms.d.ts +6 -2
  126. package/dist/mocks/app-forms.js +11 -4
  127. package/dist/openapi/v1/openapi.yaml +3 -3
  128. package/dist/playground/index.d.ts +4 -5
  129. package/dist/playground/index.js +4 -32
  130. package/dist/playground/mount.d.ts +25 -0
  131. package/dist/playground/mount.js +50 -20
  132. package/dist/registry/{BaseRegistry.d.ts → BaseRegistry.svelte.d.ts} +22 -1
  133. package/dist/registry/{BaseRegistry.js → BaseRegistry.svelte.js} +37 -1
  134. package/dist/registry/builtinFormats.d.ts +9 -18
  135. package/dist/registry/builtinFormats.js +9 -39
  136. package/dist/registry/builtinNodeTypes.d.ts +53 -0
  137. package/dist/registry/builtinNodeTypes.js +67 -0
  138. package/dist/registry/builtinNodes.d.ts +2 -64
  139. package/dist/registry/builtinNodes.js +7 -103
  140. package/dist/registry/index.d.ts +3 -4
  141. package/dist/registry/index.js +4 -6
  142. package/dist/registry/nodeComponentRegistry.d.ts +182 -15
  143. package/dist/registry/nodeComponentRegistry.js +235 -17
  144. package/dist/registry/workflowFormatRegistry.d.ts +14 -9
  145. package/dist/registry/workflowFormatRegistry.js +24 -8
  146. package/dist/{schema → schemas}/index.d.ts +2 -2
  147. package/dist/{schema → schemas}/index.js +2 -2
  148. package/dist/schemas/v1/workflow.schema.json +3 -3
  149. package/dist/services/agentSpecExecutionService.d.ts +0 -2
  150. package/dist/services/agentSpecExecutionService.js +0 -3
  151. package/dist/services/apiVariableService.d.ts +2 -1
  152. package/dist/services/apiVariableService.js +16 -47
  153. package/dist/services/autoSaveService.d.ts +7 -0
  154. package/dist/services/autoSaveService.js +6 -4
  155. package/dist/services/categoriesApi.js +3 -6
  156. package/dist/services/chatService.d.ts +9 -4
  157. package/dist/services/chatService.js +23 -28
  158. package/dist/services/draftStorage.d.ts +129 -13
  159. package/dist/services/draftStorage.js +185 -37
  160. package/dist/services/dynamicSchemaService.d.ts +2 -1
  161. package/dist/services/dynamicSchemaService.js +5 -22
  162. package/dist/services/globalSave.d.ts +13 -12
  163. package/dist/services/globalSave.js +29 -51
  164. package/dist/services/historyService.d.ts +9 -3
  165. package/dist/services/historyService.js +9 -3
  166. package/dist/services/interruptService.d.ts +15 -9
  167. package/dist/services/interruptService.js +35 -37
  168. package/dist/services/nodeExecutionService.d.ts +18 -3
  169. package/dist/services/nodeExecutionService.js +71 -45
  170. package/dist/services/playgroundService.d.ts +16 -10
  171. package/dist/services/playgroundService.js +42 -43
  172. package/dist/services/portConfigApi.js +3 -6
  173. package/dist/services/settingsService.d.ts +9 -4
  174. package/dist/services/settingsService.js +23 -12
  175. package/dist/services/variableService.d.ts +2 -1
  176. package/dist/services/variableService.js +2 -2
  177. package/dist/services/workflowStorage.js +6 -6
  178. package/dist/stores/apiContext.d.ts +56 -0
  179. package/dist/stores/apiContext.js +80 -0
  180. package/dist/stores/categoriesStore.svelte.d.ts +28 -23
  181. package/dist/stores/categoriesStore.svelte.js +69 -64
  182. package/dist/stores/getInstance.svelte.d.ts +39 -0
  183. package/dist/stores/getInstance.svelte.js +65 -0
  184. package/dist/stores/historyStore.svelte.d.ts +77 -93
  185. package/dist/stores/historyStore.svelte.js +134 -160
  186. package/dist/stores/instanceContainer.svelte.d.ts +111 -0
  187. package/dist/stores/instanceContainer.svelte.js +114 -0
  188. package/dist/stores/interruptStore.svelte.d.ts +112 -82
  189. package/dist/stores/interruptStore.svelte.js +253 -226
  190. package/dist/stores/pipelinePanelStore.svelte.d.ts +27 -3
  191. package/dist/stores/pipelinePanelStore.svelte.js +61 -14
  192. package/dist/stores/playgroundStore.svelte.d.ts +169 -222
  193. package/dist/stores/playgroundStore.svelte.js +513 -580
  194. package/dist/stores/portCoordinateStore.svelte.d.ts +57 -51
  195. package/dist/stores/portCoordinateStore.svelte.js +109 -98
  196. package/dist/stores/settingsStore.svelte.d.ts +4 -1
  197. package/dist/stores/settingsStore.svelte.js +47 -12
  198. package/dist/stores/workflowStore.svelte.d.ts +178 -213
  199. package/dist/stores/workflowStore.svelte.js +449 -501
  200. package/dist/stories/EdgeDecorator.svelte +5 -2
  201. package/dist/stories/NodeDecorator.svelte +5 -3
  202. package/dist/svelte-app.d.ts +60 -10
  203. package/dist/svelte-app.js +159 -54
  204. package/dist/types/auth.d.ts +9 -51
  205. package/dist/types/auth.js +4 -54
  206. package/dist/types/events.d.ts +6 -3
  207. package/dist/types/index.d.ts +37 -5
  208. package/dist/types/index.js +0 -1
  209. package/dist/types/navbar.d.ts +7 -0
  210. package/dist/types/playground.d.ts +18 -3
  211. package/dist/types/settings.d.ts +13 -0
  212. package/dist/types/settings.js +1 -0
  213. package/dist/utils/colors.d.ts +47 -21
  214. package/dist/utils/colors.js +69 -68
  215. package/dist/utils/connections.d.ts +9 -15
  216. package/dist/utils/connections.js +13 -32
  217. package/dist/utils/duration.d.ts +13 -0
  218. package/dist/utils/duration.js +45 -0
  219. package/dist/utils/edgeStyling.js +9 -5
  220. package/dist/utils/fetchWithAuth.d.ts +36 -15
  221. package/dist/utils/fetchWithAuth.js +53 -23
  222. package/dist/utils/icons.d.ts +5 -2
  223. package/dist/utils/icons.js +6 -5
  224. package/dist/utils/nodeSwap.d.ts +6 -2
  225. package/dist/utils/nodeSwap.js +62 -126
  226. package/dist/utils/nodeTypes.d.ts +17 -8
  227. package/dist/utils/nodeTypes.js +27 -20
  228. package/dist/utils/performanceUtils.js +7 -0
  229. package/package.json +7 -5
  230. package/dist/messages/deprecation.d.ts +0 -20
  231. package/dist/messages/deprecation.js +0 -33
  232. package/dist/registry/plugin.d.ts +0 -215
  233. package/dist/registry/plugin.js +0 -249
  234. package/dist/services/api.d.ts +0 -129
  235. package/dist/services/api.js +0 -217
@@ -20,10 +20,10 @@ export async function saveWorkflow(workflow) {
20
20
  ...workflow,
21
21
  id,
22
22
  metadata: {
23
- version: '1.0.0',
24
- createdAt: new Date().toISOString(),
25
- updatedAt: new Date().toISOString(),
26
- ...workflow.metadata
23
+ ...workflow.metadata,
24
+ schemaVersion: workflow.metadata?.schemaVersion ?? '1.0.0',
25
+ createdAt: workflow.metadata?.createdAt ?? new Date().toISOString(),
26
+ updatedAt: workflow.metadata?.updatedAt ?? new Date().toISOString()
27
27
  }
28
28
  };
29
29
  workflows.set(id, newWorkflow);
@@ -42,7 +42,7 @@ export async function updateWorkflow(id, workflow) {
42
42
  ...workflow,
43
43
  id, // Ensure ID doesn't change
44
44
  metadata: {
45
- version: existing.metadata?.version || '1.0.0',
45
+ schemaVersion: existing.metadata?.schemaVersion || '1.0.0',
46
46
  createdAt: existing.metadata?.createdAt || new Date().toISOString(),
47
47
  updatedAt: new Date().toISOString(),
48
48
  author: workflow.metadata?.author || existing.metadata?.author,
@@ -105,7 +105,7 @@ export async function initializeSampleWorkflows() {
105
105
  nodes: [],
106
106
  edges: [],
107
107
  metadata: {
108
- version: '1.0.0',
108
+ schemaVersion: '1.0.0',
109
109
  createdAt: new Date().toISOString(),
110
110
  updatedAt: new Date().toISOString(),
111
111
  author: 'System',
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Per-instance API context for FlowDrop.
3
+ *
4
+ * Holds the endpoint configuration and auth provider for one FlowDrop
5
+ * instance and lazily exposes an {@link EnhancedFlowDropApiClient} built from
6
+ * them. Replaces the former module-level singleton in `services/api.ts`:
7
+ * each instance owns its own configuration so multiple editors can talk to
8
+ * different backends on a single page.
9
+ *
10
+ * Resolved in components via `getInstance().api`; configured at mount time by
11
+ * `mountFlowDropApp` / `mountPlayground` (or `<App>` when used directly).
12
+ *
13
+ * @module stores/apiContext
14
+ */
15
+ import type { EndpointConfig } from '../config/endpoints.js';
16
+ import type { AuthProvider } from '../types/auth.js';
17
+ import { EnhancedFlowDropApiClient } from '../api/enhanced-client.js';
18
+ /**
19
+ * Per-instance endpoint configuration, auth provider, and API client.
20
+ *
21
+ * The config is `null` until {@link configure} is called — mirroring the
22
+ * legacy "throws if not configured" contract. The client is created lazily on
23
+ * first access and rebuilt whenever the configuration changes.
24
+ */
25
+ export declare class ApiContext {
26
+ #private;
27
+ /** The current endpoint configuration, or null until {@link configure}d. */
28
+ get config(): EndpointConfig | null;
29
+ /** The current auth provider (defaults to {@link NoAuthProvider}). */
30
+ get authProvider(): AuthProvider;
31
+ /**
32
+ * The API client for this instance, created lazily from the configured
33
+ * endpoints and auth provider.
34
+ *
35
+ * @throws Error if the context has not been configured yet.
36
+ */
37
+ get client(): EnhancedFlowDropApiClient;
38
+ /**
39
+ * Configure this instance's endpoints and (optionally) auth provider.
40
+ * Discards any previously built client so the next access rebuilds it.
41
+ */
42
+ configure(config: EndpointConfig, authProvider?: AuthProvider): void;
43
+ /**
44
+ * Swap the auth provider at runtime — e.g. on login or logout — without
45
+ * reconfiguring endpoints or remounting. Propagates to the live client so
46
+ * in-flight components keep working against the same instance.
47
+ *
48
+ * Per-instance services read `fd.api.authProvider` per request, so they pick
49
+ * up the new provider on their next call automatically.
50
+ *
51
+ * @param authProvider - The new authentication provider
52
+ */
53
+ setAuthProvider(authProvider: AuthProvider): void;
54
+ /** Whether {@link configure} has been called with a usable config. */
55
+ isConfigured(): boolean;
56
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Per-instance API context for FlowDrop.
3
+ *
4
+ * Holds the endpoint configuration and auth provider for one FlowDrop
5
+ * instance and lazily exposes an {@link EnhancedFlowDropApiClient} built from
6
+ * them. Replaces the former module-level singleton in `services/api.ts`:
7
+ * each instance owns its own configuration so multiple editors can talk to
8
+ * different backends on a single page.
9
+ *
10
+ * Resolved in components via `getInstance().api`; configured at mount time by
11
+ * `mountFlowDropApp` / `mountPlayground` (or `<App>` when used directly).
12
+ *
13
+ * @module stores/apiContext
14
+ */
15
+ import { NoAuthProvider } from '../types/auth.js';
16
+ import { EnhancedFlowDropApiClient } from '../api/enhanced-client.js';
17
+ /**
18
+ * Per-instance endpoint configuration, auth provider, and API client.
19
+ *
20
+ * The config is `null` until {@link configure} is called — mirroring the
21
+ * legacy "throws if not configured" contract. The client is created lazily on
22
+ * first access and rebuilt whenever the configuration changes.
23
+ */
24
+ export class ApiContext {
25
+ #config = null;
26
+ #authProvider = new NoAuthProvider();
27
+ #client = null;
28
+ /** The current endpoint configuration, or null until {@link configure}d. */
29
+ get config() {
30
+ return this.#config;
31
+ }
32
+ /** The current auth provider (defaults to {@link NoAuthProvider}). */
33
+ get authProvider() {
34
+ return this.#authProvider;
35
+ }
36
+ /**
37
+ * The API client for this instance, created lazily from the configured
38
+ * endpoints and auth provider.
39
+ *
40
+ * @throws Error if the context has not been configured yet.
41
+ */
42
+ get client() {
43
+ if (!this.#config) {
44
+ throw new Error('Endpoint configuration not set. Configure the instance via fd.api.configure() ' +
45
+ '(done automatically by mountFlowDropApp / <App>) before using fd.api.client.');
46
+ }
47
+ return (this.#client ??= new EnhancedFlowDropApiClient(this.#config, this.#authProvider));
48
+ }
49
+ /**
50
+ * Configure this instance's endpoints and (optionally) auth provider.
51
+ * Discards any previously built client so the next access rebuilds it.
52
+ */
53
+ configure(config, authProvider) {
54
+ this.#config = config;
55
+ if (authProvider) {
56
+ this.#authProvider = authProvider;
57
+ }
58
+ // Drop the cached client so it picks up the new config/auth on next access.
59
+ this.#client = null;
60
+ }
61
+ /**
62
+ * Swap the auth provider at runtime — e.g. on login or logout — without
63
+ * reconfiguring endpoints or remounting. Propagates to the live client so
64
+ * in-flight components keep working against the same instance.
65
+ *
66
+ * Per-instance services read `fd.api.authProvider` per request, so they pick
67
+ * up the new provider on their next call automatically.
68
+ *
69
+ * @param authProvider - The new authentication provider
70
+ */
71
+ setAuthProvider(authProvider) {
72
+ this.#authProvider = authProvider;
73
+ // Keep the cached client (and its in-flight consumers) in sync.
74
+ this.#client?.setAuthProvider(authProvider);
75
+ }
76
+ /** Whether {@link configure} has been called with a usable config. */
77
+ isConfigured() {
78
+ return Boolean(this.#config);
79
+ }
80
+ }
@@ -3,30 +3,35 @@
3
3
  *
4
4
  * Manages category definitions with merged defaults and API-provided overrides.
5
5
  * Exposes lookup helpers for icon, color, and label resolution.
6
+ *
7
+ * The reactive state lives in the {@link CategoriesStore} class — one per
8
+ * FlowDrop instance, resolved in components via `getInstance().categories`.
9
+ *
10
+ * @module stores/categoriesStore
6
11
  */
7
12
  import type { CategoryDefinition, NodeCategory } from '../types/index.js';
8
13
  /**
9
- * Get all category definitions, sorted by weight.
10
- */
11
- export declare function getCategories(): CategoryDefinition[];
12
- /**
13
- * Initialize categories with API data, merging with defaults.
14
- * API categories override defaults by name; custom categories are appended.
15
- */
16
- export declare function initializeCategories(apiCategories: CategoryDefinition[]): void;
17
- /**
18
- * Get the display label for a category.
19
- */
20
- export declare function getCategoryLabel(category: NodeCategory): string;
21
- /**
22
- * Get the icon for a category.
23
- */
24
- export declare function getCategoryIcon(category: NodeCategory): string;
25
- /**
26
- * Get the color token for a category.
27
- */
28
- export declare function getCategoryColor(category: NodeCategory): string;
29
- /**
30
- * Get the full category definition, or undefined if not found.
14
+ * Per-instance category definitions with a derived name→definition lookup.
15
+ *
16
+ * Reads go through getters backed by `$state`/`$derived`, so they track
17
+ * reactively in templates and `$derived`, exactly like the legacy
18
+ * module-level functions did.
31
19
  */
32
- export declare function getCategoryDefinition(category: NodeCategory): CategoryDefinition | undefined;
20
+ export declare class CategoriesStore {
21
+ #private;
22
+ /** All category definitions, sorted by weight (reactive). */
23
+ get categories(): CategoryDefinition[];
24
+ /**
25
+ * Initialize categories with API data, merging with defaults.
26
+ * API categories override defaults by name; custom categories are appended.
27
+ */
28
+ initialize(apiCategories: CategoryDefinition[]): void;
29
+ /** Get the display label for a category. */
30
+ getLabel(category: NodeCategory): string;
31
+ /** Get the icon for a category. */
32
+ getIcon(category: NodeCategory): string;
33
+ /** Get the color token for a category. */
34
+ getColor(category: NodeCategory): string;
35
+ /** Get the full category definition, or undefined if not found. */
36
+ getDefinition(category: NodeCategory): CategoryDefinition | undefined;
37
+ }
@@ -3,75 +3,80 @@
3
3
  *
4
4
  * Manages category definitions with merged defaults and API-provided overrides.
5
5
  * Exposes lookup helpers for icon, color, and label resolution.
6
+ *
7
+ * The reactive state lives in the {@link CategoriesStore} class — one per
8
+ * FlowDrop instance, resolved in components via `getInstance().categories`.
9
+ *
10
+ * @module stores/categoriesStore
6
11
  */
7
12
  import { DEFAULT_CATEGORIES } from '../config/defaultCategories.js';
13
+ // =========================================================================
14
+ // CategoriesStore (per-instance reactive state)
15
+ // =========================================================================
8
16
  /**
9
- * Internal reactive state holding the category definitions.
10
- * Initialized with defaults, updated when API data is fetched.
11
- */
12
- let categoriesState = $state([...DEFAULT_CATEGORIES]);
13
- /**
14
- * Derived lookup map: category name → CategoryDefinition
17
+ * Per-instance category definitions with a derived name→definition lookup.
18
+ *
19
+ * Reads go through getters backed by `$state`/`$derived`, so they track
20
+ * reactively in templates and `$derived`, exactly like the legacy
21
+ * module-level functions did.
15
22
  */
16
- let categoryMap = $derived((() => {
17
- const map = new Map();
18
- for (const cat of categoriesState) {
19
- map.set(cat.name, cat);
23
+ export class CategoriesStore {
24
+ /**
25
+ * Reactive state holding the category definitions.
26
+ * Initialized with defaults, updated when API data is fetched.
27
+ */
28
+ #categories = $state([...DEFAULT_CATEGORIES]);
29
+ /** Derived lookup map: category name → CategoryDefinition. */
30
+ #categoryMap = $derived((() => {
31
+ const map = new Map();
32
+ for (const cat of this.#categories) {
33
+ map.set(cat.name, cat);
34
+ }
35
+ return map;
36
+ })());
37
+ /** All category definitions, sorted by weight (reactive). */
38
+ get categories() {
39
+ return [...this.#categories].sort((a, b) => (a.weight ?? 999) - (b.weight ?? 999));
20
40
  }
21
- return map;
22
- })());
23
- /**
24
- * Get all category definitions, sorted by weight.
25
- */
26
- export function getCategories() {
27
- return [...categoriesState].sort((a, b) => (a.weight ?? 999) - (b.weight ?? 999));
28
- }
29
- /**
30
- * Initialize categories with API data, merging with defaults.
31
- * API categories override defaults by name; custom categories are appended.
32
- */
33
- export function initializeCategories(apiCategories) {
34
- const defaultMap = new Map();
35
- for (const cat of DEFAULT_CATEGORIES) {
36
- defaultMap.set(cat.name, cat);
41
+ /**
42
+ * Initialize categories with API data, merging with defaults.
43
+ * API categories override defaults by name; custom categories are appended.
44
+ */
45
+ initialize(apiCategories) {
46
+ const defaultMap = new Map();
47
+ for (const cat of DEFAULT_CATEGORIES) {
48
+ defaultMap.set(cat.name, cat);
49
+ }
50
+ // API categories override defaults by name
51
+ for (const cat of apiCategories) {
52
+ defaultMap.set(cat.name, {
53
+ ...defaultMap.get(cat.name),
54
+ ...cat
55
+ });
56
+ }
57
+ this.#categories = Array.from(defaultMap.values());
37
58
  }
38
- // API categories override defaults by name
39
- for (const cat of apiCategories) {
40
- defaultMap.set(cat.name, {
41
- ...defaultMap.get(cat.name),
42
- ...cat
43
- });
59
+ /** Get the display label for a category. */
60
+ getLabel(category) {
61
+ const def = this.#categoryMap.get(category);
62
+ if (def?.label)
63
+ return def.label;
64
+ // Auto-generate: capitalize each word
65
+ return category
66
+ .split(/[\s_-]+/)
67
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
68
+ .join(' ');
69
+ }
70
+ /** Get the icon for a category. */
71
+ getIcon(category) {
72
+ return this.#categoryMap.get(category)?.icon ?? 'mdi:folder';
73
+ }
74
+ /** Get the color token for a category. */
75
+ getColor(category) {
76
+ return this.#categoryMap.get(category)?.color ?? 'var(--fd-node-slate)';
77
+ }
78
+ /** Get the full category definition, or undefined if not found. */
79
+ getDefinition(category) {
80
+ return this.#categoryMap.get(category);
44
81
  }
45
- categoriesState = Array.from(defaultMap.values());
46
- }
47
- /**
48
- * Get the display label for a category.
49
- */
50
- export function getCategoryLabel(category) {
51
- const def = categoryMap.get(category);
52
- if (def?.label)
53
- return def.label;
54
- // Auto-generate: capitalize each word
55
- return category
56
- .split(/[\s_-]+/)
57
- .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
58
- .join(' ');
59
- }
60
- /**
61
- * Get the icon for a category.
62
- */
63
- export function getCategoryIcon(category) {
64
- return categoryMap.get(category)?.icon ?? 'mdi:folder';
65
- }
66
- /**
67
- * Get the color token for a category.
68
- */
69
- export function getCategoryColor(category) {
70
- return categoryMap.get(category)?.color ?? 'var(--fd-node-slate)';
71
- }
72
- /**
73
- * Get the full category definition, or undefined if not found.
74
- */
75
- export function getCategoryDefinition(category) {
76
- return categoryMap.get(category);
77
82
  }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Per-component access to the FlowDrop instance container.
3
+ *
4
+ * Components call `getInstance()` during init to resolve the instance
5
+ * provided by the nearest `<App>` / `<WorkflowEditor>` via Svelte context.
6
+ * When no provider exists (legacy single-instance usage), it falls back to
7
+ * the browser-only default instance.
8
+ *
9
+ * @module stores/getInstance
10
+ */
11
+ import { type FlowDropInstance } from './instanceContainer.svelte.js';
12
+ /**
13
+ * Context key under which the FlowDrop instance is provided.
14
+ * A Symbol (matching `messages/context.ts`) so consumer context can't collide.
15
+ */
16
+ export declare const FLOWDROP_INSTANCE_KEY: unique symbol;
17
+ /**
18
+ * Resolve the FlowDrop instance for the current component tree.
19
+ *
20
+ * Must be called during component initialisation (it reads Svelte context).
21
+ *
22
+ * Unlike the messages-context fallback (immutable defaults, silent), this
23
+ * fallback hands out *mutable shared state*, so it warns once in dev and
24
+ * throws during SSR rather than leaking state across server requests.
25
+ */
26
+ export declare function getInstance(): FlowDropInstance;
27
+ /**
28
+ * Resolve and provide the FlowDrop instance for a provider component
29
+ * (`<App>`, `<WorkflowEditor>`, `<Playground>`, `<PlaygroundStudio>`).
30
+ *
31
+ * Must be called during component initialisation. Resolution order:
32
+ * 1. An explicitly passed instance (from a mount function or consumer)
33
+ * 2. An instance already in context (provider nested inside another provider)
34
+ * 3. Browser: the page-default instance (legacy single-instance behavior)
35
+ * Server: a fresh per-render instance (no cross-request leakage)
36
+ *
37
+ * The resolved instance is (re-)provided via context for all children.
38
+ */
39
+ export declare function provideInstance(explicit?: FlowDropInstance): FlowDropInstance;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Per-component access to the FlowDrop instance container.
3
+ *
4
+ * Components call `getInstance()` during init to resolve the instance
5
+ * provided by the nearest `<App>` / `<WorkflowEditor>` via Svelte context.
6
+ * When no provider exists (legacy single-instance usage), it falls back to
7
+ * the browser-only default instance.
8
+ *
9
+ * @module stores/getInstance
10
+ */
11
+ import { DEV } from 'esm-env';
12
+ import { getContext, setContext } from 'svelte';
13
+ import { createFlowDropInstance, getDefaultInstance } from './instanceContainer.svelte.js';
14
+ /**
15
+ * Context key under which the FlowDrop instance is provided.
16
+ * A Symbol (matching `messages/context.ts`) so consumer context can't collide.
17
+ */
18
+ export const FLOWDROP_INSTANCE_KEY = Symbol('flowdrop.instance');
19
+ let warnedAboutFallback = false;
20
+ /**
21
+ * Resolve the FlowDrop instance for the current component tree.
22
+ *
23
+ * Must be called during component initialisation (it reads Svelte context).
24
+ *
25
+ * Unlike the messages-context fallback (immutable defaults, silent), this
26
+ * fallback hands out *mutable shared state*, so it warns once in dev and
27
+ * throws during SSR rather than leaking state across server requests.
28
+ */
29
+ export function getInstance() {
30
+ const instance = getContext(FLOWDROP_INSTANCE_KEY);
31
+ if (instance) {
32
+ return instance;
33
+ }
34
+ if (typeof window === 'undefined') {
35
+ throw new Error('[flowdrop] No FlowDrop instance in context during SSR. Render inside ' +
36
+ '<App> or <WorkflowEditor> (which set context), or provide one with ' +
37
+ 'setContext(FLOWDROP_INSTANCE_KEY, createFlowDropInstance()).');
38
+ }
39
+ if (DEV && !warnedAboutFallback) {
40
+ warnedAboutFallback = true;
41
+ // eslint-disable-next-line no-console -- intentional one-time dev diagnostic for silent shared-state fallback
42
+ console.warn('[flowdrop] getInstance() fell back to the page-default instance — ' +
43
+ 'fine for a single editor, but two editors mounted this way will share state.');
44
+ }
45
+ return getDefaultInstance();
46
+ }
47
+ /**
48
+ * Resolve and provide the FlowDrop instance for a provider component
49
+ * (`<App>`, `<WorkflowEditor>`, `<Playground>`, `<PlaygroundStudio>`).
50
+ *
51
+ * Must be called during component initialisation. Resolution order:
52
+ * 1. An explicitly passed instance (from a mount function or consumer)
53
+ * 2. An instance already in context (provider nested inside another provider)
54
+ * 3. Browser: the page-default instance (legacy single-instance behavior)
55
+ * Server: a fresh per-render instance (no cross-request leakage)
56
+ *
57
+ * The resolved instance is (re-)provided via context for all children.
58
+ */
59
+ export function provideInstance(explicit) {
60
+ const instance = explicit ??
61
+ getContext(FLOWDROP_INSTANCE_KEY) ??
62
+ (typeof window === 'undefined' ? createFlowDropInstance() : getDefaultInstance());
63
+ setContext(FLOWDROP_INSTANCE_KEY, instance);
64
+ return instance;
65
+ }