@flowdrop/flowdrop 1.15.0 → 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +475 -0
- package/MIGRATION-2.0.md +472 -0
- package/README.md +23 -23
- package/dist/adapters/WorkflowAdapter.d.ts +1 -1
- package/dist/adapters/WorkflowAdapter.js +14 -8
- package/dist/adapters/agentspec/AgentSpecAdapter.js +7 -7
- package/dist/chat/batchFeedback.d.ts +39 -0
- package/dist/chat/batchFeedback.js +51 -0
- package/dist/commands/executor.js +15 -1
- package/dist/commands/storeIntegration.svelte.d.ts +4 -1
- package/dist/commands/storeIntegration.svelte.js +26 -21
- package/dist/commands/types.d.ts +2 -0
- package/dist/components/App.svelte +162 -192
- package/dist/components/App.svelte.d.ts +47 -8
- package/dist/components/ConfigForm.svelte +71 -47
- package/dist/components/ConfigModal.svelte +7 -2
- package/dist/components/ConnectionLine.svelte +4 -2
- package/dist/components/Navbar.svelte +61 -1
- package/dist/components/NodeSidebar.svelte +27 -45
- package/dist/components/NodeStatusOverlay.svelte +94 -6
- package/dist/components/NodeSwapPicker.svelte +10 -8
- package/dist/components/PipelineStatus.svelte +16 -67
- package/dist/components/PortCoordinateTracker.svelte +5 -6
- package/dist/components/SchemaForm.stories.svelte +1 -3
- package/dist/components/SchemaForm.svelte +18 -25
- package/dist/components/SchemaForm.svelte.d.ts +0 -8
- package/dist/components/SettingsModal.svelte +8 -3
- package/dist/components/SettingsPanel.svelte +20 -4
- package/dist/components/SwapMappingEditor.svelte +67 -49
- package/dist/components/SwapMappingEditor.svelte.d.ts +0 -2
- package/dist/components/UniversalNode.svelte +9 -7
- package/dist/components/WorkflowEditor.svelte +118 -111
- package/dist/components/WorkflowEditor.svelte.d.ts +18 -10
- package/dist/components/chat/AIChatPanel.svelte +93 -89
- package/dist/components/chat/AIChatPanel.svelte.d.ts +0 -4
- package/dist/components/chat/CommandPreview.svelte +2 -1
- package/dist/components/console/CommandConsole.svelte +7 -5
- package/dist/components/console/ConsoleAutocomplete.svelte +10 -11
- package/dist/components/console/ConsoleAutocomplete.svelte.d.ts +6 -0
- package/dist/components/console/ConsoleInput.svelte +15 -6
- package/dist/components/console/ConsoleOutput.svelte +2 -1
- package/dist/components/form/FormArray.svelte +5 -9
- package/dist/components/form/FormArray.svelte.d.ts +2 -1
- package/dist/components/form/FormAutocomplete.svelte +8 -6
- package/dist/components/form/FormField.svelte +4 -2
- package/dist/components/form/FormFieldLight.svelte +4 -2
- package/dist/components/form/FormMarkdownEditor.svelte +9 -4
- package/dist/components/form/FormRangeField.svelte +1 -0
- package/dist/components/form/FormTemplateEditor.svelte +11 -3
- package/dist/components/form/FormToggle.svelte +5 -12
- package/dist/components/form/FormToggle.svelte.d.ts +4 -2
- package/dist/components/form/templateAutocomplete.js +1 -5
- package/dist/components/form/types.d.ts +1 -14
- package/dist/components/interrupt/FormPrompt.svelte +3 -2
- package/dist/components/interrupt/InterruptBubble.svelte +16 -17
- package/dist/components/interrupt/ReviewPrompt.svelte +10 -3
- package/dist/components/interrupt/TextInputPrompt.svelte +2 -1
- package/dist/components/layouts/MainLayout.svelte +20 -13
- package/dist/components/layouts/MainLayout.svelte.d.ts +4 -0
- package/dist/components/nodes/AtomNode.svelte +17 -5
- package/dist/components/nodes/GatewayNode.svelte +19 -10
- package/dist/components/nodes/IdeaNode.svelte +7 -0
- package/dist/components/nodes/SimpleNode.svelte +11 -6
- package/dist/components/nodes/SquareNode.svelte +15 -8
- package/dist/components/nodes/TerminalNode.svelte +9 -4
- package/dist/components/nodes/ToolNode.svelte +7 -1
- package/dist/components/nodes/WorkflowNode.svelte +16 -7
- package/dist/components/playground/ChatInput.svelte +11 -14
- package/dist/components/playground/ChatPanel.svelte +6 -49
- package/dist/components/playground/ChatPanel.svelte.d.ts +0 -14
- package/dist/components/playground/ControlPanel.svelte +134 -123
- package/dist/components/playground/ControlPanel.svelte.d.ts +3 -0
- package/dist/components/playground/ExecutionLogs.svelte +11 -9
- package/dist/components/playground/InputCollector.svelte +11 -9
- package/dist/components/playground/MessageStream.svelte +17 -23
- package/dist/components/playground/PipelineKanbanView.svelte +65 -6
- package/dist/components/playground/PipelinePanel.svelte +11 -5
- package/dist/components/playground/PipelineTableView.svelte +186 -44
- package/dist/components/playground/Playground.svelte +90 -92
- package/dist/components/playground/Playground.svelte.d.ts +2 -0
- package/dist/components/playground/PlaygroundApp.svelte +6 -1
- package/dist/components/playground/PlaygroundApp.svelte.d.ts +3 -0
- package/dist/components/playground/PlaygroundModal.svelte +13 -3
- package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -0
- package/dist/components/playground/PlaygroundStudio.svelte +34 -32
- package/dist/components/playground/PlaygroundStudio.svelte.d.ts +3 -0
- package/dist/components/playground/SessionManager.svelte +9 -12
- package/dist/components/playground/pipelineViewUtils.svelte.d.ts +28 -0
- package/dist/components/playground/pipelineViewUtils.svelte.js +38 -1
- package/dist/config/endpoints.d.ts +0 -7
- package/dist/config/endpoints.js +2 -10
- package/dist/core/index.d.ts +4 -4
- package/dist/core/index.js +6 -6
- package/dist/display/index.d.ts +0 -2
- package/dist/display/index.js +0 -6
- package/dist/editor/index.d.ts +19 -20
- package/dist/editor/index.js +25 -35
- package/dist/form/code.d.ts +25 -15
- package/dist/form/code.js +44 -41
- package/dist/form/fieldRegistry.d.ts +17 -13
- package/dist/form/fieldRegistry.js +32 -12
- package/dist/form/full.d.ts +17 -13
- package/dist/form/full.js +22 -27
- package/dist/form/index.d.ts +3 -3
- package/dist/form/index.js +3 -3
- package/dist/form/markdown.d.ts +13 -8
- package/dist/form/markdown.js +22 -23
- package/dist/helpers/proximityConnect.d.ts +3 -2
- package/dist/helpers/proximityConnect.js +2 -5
- package/dist/helpers/workflowEditorHelper.d.ts +12 -5
- package/dist/helpers/workflowEditorHelper.js +27 -25
- package/dist/index.d.ts +28 -24
- package/dist/index.js +27 -50
- package/dist/messages/defaults.d.ts +2 -5
- package/dist/messages/defaults.js +3 -6
- package/dist/messages/index.d.ts +0 -1
- package/dist/messages/index.js +0 -1
- package/dist/mocks/app-forms.d.ts +6 -2
- package/dist/mocks/app-forms.js +11 -4
- package/dist/openapi/v1/openapi.yaml +3 -3
- package/dist/playground/index.d.ts +2 -3
- package/dist/playground/index.js +2 -30
- package/dist/playground/mount.d.ts +15 -0
- package/dist/playground/mount.js +46 -20
- package/dist/registry/{BaseRegistry.d.ts → BaseRegistry.svelte.d.ts} +22 -1
- package/dist/registry/{BaseRegistry.js → BaseRegistry.svelte.js} +37 -1
- package/dist/registry/builtinFormats.d.ts +9 -18
- package/dist/registry/builtinFormats.js +9 -39
- package/dist/registry/builtinNodes.d.ts +0 -25
- package/dist/registry/builtinNodes.js +1 -50
- package/dist/registry/index.d.ts +3 -4
- package/dist/registry/index.js +4 -6
- package/dist/registry/nodeComponentRegistry.d.ts +182 -15
- package/dist/registry/nodeComponentRegistry.js +235 -17
- package/dist/registry/workflowFormatRegistry.d.ts +14 -9
- package/dist/registry/workflowFormatRegistry.js +24 -8
- package/dist/{schema → schemas}/index.d.ts +2 -2
- package/dist/{schema → schemas}/index.js +2 -2
- package/dist/schemas/v1/workflow.schema.json +3 -3
- package/dist/services/agentSpecExecutionService.js +0 -1
- package/dist/services/apiVariableService.d.ts +2 -1
- package/dist/services/apiVariableService.js +5 -22
- package/dist/services/autoSaveService.d.ts +7 -0
- package/dist/services/autoSaveService.js +6 -4
- package/dist/services/chatService.d.ts +8 -4
- package/dist/services/chatService.js +15 -15
- package/dist/services/draftStorage.d.ts +129 -13
- package/dist/services/draftStorage.js +185 -37
- package/dist/services/dynamicSchemaService.d.ts +2 -1
- package/dist/services/dynamicSchemaService.js +5 -22
- package/dist/services/globalSave.d.ts +13 -12
- package/dist/services/globalSave.js +29 -51
- package/dist/services/historyService.d.ts +9 -3
- package/dist/services/historyService.js +9 -3
- package/dist/services/interruptService.d.ts +14 -9
- package/dist/services/interruptService.js +27 -27
- package/dist/services/nodeExecutionService.d.ts +18 -3
- package/dist/services/nodeExecutionService.js +71 -45
- package/dist/services/playgroundService.d.ts +14 -9
- package/dist/services/playgroundService.js +31 -30
- package/dist/services/variableService.d.ts +2 -1
- package/dist/services/variableService.js +2 -2
- package/dist/services/workflowStorage.js +6 -6
- package/dist/stores/apiContext.d.ts +45 -0
- package/dist/stores/apiContext.js +65 -0
- package/dist/stores/categoriesStore.svelte.d.ts +28 -23
- package/dist/stores/categoriesStore.svelte.js +70 -64
- package/dist/stores/getInstance.svelte.d.ts +39 -0
- package/dist/stores/getInstance.svelte.js +65 -0
- package/dist/stores/historyStore.svelte.d.ts +77 -93
- package/dist/stores/historyStore.svelte.js +134 -160
- package/dist/stores/instanceContainer.svelte.d.ts +111 -0
- package/dist/stores/instanceContainer.svelte.js +114 -0
- package/dist/stores/interruptStore.svelte.d.ts +112 -82
- package/dist/stores/interruptStore.svelte.js +253 -226
- package/dist/stores/pipelinePanelStore.svelte.d.ts +27 -3
- package/dist/stores/pipelinePanelStore.svelte.js +61 -14
- package/dist/stores/playgroundStore.svelte.d.ts +169 -222
- package/dist/stores/playgroundStore.svelte.js +515 -580
- package/dist/stores/portCoordinateStore.svelte.d.ts +57 -51
- package/dist/stores/portCoordinateStore.svelte.js +109 -98
- package/dist/stores/settingsStore.svelte.d.ts +4 -1
- package/dist/stores/settingsStore.svelte.js +47 -12
- package/dist/stores/workflowStore.svelte.d.ts +178 -213
- package/dist/stores/workflowStore.svelte.js +449 -501
- package/dist/stories/EdgeDecorator.svelte +5 -2
- package/dist/stories/NodeDecorator.svelte +5 -3
- package/dist/svelte-app.d.ts +60 -10
- package/dist/svelte-app.js +157 -53
- package/dist/types/events.d.ts +6 -3
- package/dist/types/index.d.ts +33 -3
- package/dist/types/navbar.d.ts +7 -0
- package/dist/types/playground.d.ts +18 -3
- package/dist/types/settings.d.ts +13 -0
- package/dist/types/settings.js +1 -0
- package/dist/utils/colors.d.ts +47 -21
- package/dist/utils/colors.js +69 -68
- package/dist/utils/connections.d.ts +9 -15
- package/dist/utils/connections.js +13 -32
- package/dist/utils/duration.d.ts +13 -0
- package/dist/utils/duration.js +45 -0
- package/dist/utils/icons.d.ts +5 -2
- package/dist/utils/icons.js +6 -5
- package/dist/utils/nodeSwap.d.ts +6 -2
- package/dist/utils/nodeSwap.js +62 -126
- package/dist/utils/nodeTypes.d.ts +17 -8
- package/dist/utils/nodeTypes.js +26 -19
- package/dist/utils/performanceUtils.js +7 -0
- package/package.json +6 -5
- package/dist/messages/deprecation.d.ts +0 -20
- package/dist/messages/deprecation.js +0 -33
- package/dist/registry/plugin.d.ts +0 -215
- package/dist/registry/plugin.js +0 -249
- package/dist/services/api.d.ts +0 -129
- package/dist/services/api.js +0 -217
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* Node Execution Service
|
|
3
3
|
* Handles fetching and managing node execution information from the backend
|
|
4
4
|
*/
|
|
5
|
-
import { getEndpointConfig } from './api.js';
|
|
6
5
|
import { buildEndpointUrl } from '../config/endpoints.js';
|
|
7
6
|
import { NODE_EXECUTION_CACHE_TIMEOUT_MS, PIPELINE_API_UNAVAILABLE_DURATION_MS } from '../config/constants.js';
|
|
8
7
|
import { logger } from '../utils/logger.js';
|
|
@@ -26,12 +25,11 @@ export class NodeExecutionService {
|
|
|
26
25
|
/**
|
|
27
26
|
* Get execution information for a specific node from pipeline data
|
|
28
27
|
*/
|
|
29
|
-
async getNodeExecutionInfo(nodeId, pipelineId) {
|
|
28
|
+
async getNodeExecutionInfo(endpointConfig, nodeId, pipelineId) {
|
|
30
29
|
if (!pipelineId) {
|
|
31
30
|
return null;
|
|
32
31
|
}
|
|
33
32
|
try {
|
|
34
|
-
const endpointConfig = getEndpointConfig();
|
|
35
33
|
if (!endpointConfig)
|
|
36
34
|
throw new Error('Endpoint config not available');
|
|
37
35
|
const url = buildEndpointUrl(endpointConfig, endpointConfig.endpoints.pipelines.get, {
|
|
@@ -45,24 +43,7 @@ export class NodeExecutionService {
|
|
|
45
43
|
const pipelineData = raw.data ?? raw;
|
|
46
44
|
const jobs = pipelineData.jobs || [];
|
|
47
45
|
const nodeStatuses = pipelineData.node_statuses || {};
|
|
48
|
-
|
|
49
|
-
const nodeJob = jobs.find((job) => job.node_id === nodeId);
|
|
50
|
-
const nodeStatus = nodeStatuses[nodeId];
|
|
51
|
-
if (!nodeJob && !nodeStatus) {
|
|
52
|
-
return {
|
|
53
|
-
status: 'idle',
|
|
54
|
-
executionCount: 0,
|
|
55
|
-
isExecuting: false
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
const executionInfo = {
|
|
59
|
-
status: this.mapJobStatusToExecutionStatus(nodeStatus?.status || nodeJob?.status || 'idle'),
|
|
60
|
-
executionCount: nodeJob?.execution_count || 0,
|
|
61
|
-
isExecuting: nodeStatus?.status === 'running' || nodeJob?.status === 'running',
|
|
62
|
-
lastExecuted: nodeJob?.last_executed || nodeStatus?.last_executed,
|
|
63
|
-
lastExecutionDuration: nodeJob?.execution_time || nodeStatus?.execution_time,
|
|
64
|
-
lastError: nodeJob?.error || nodeStatus?.error
|
|
65
|
-
};
|
|
46
|
+
const executionInfo = this.buildNodeExecutionInfo(nodeId, nodeStatuses[nodeId], jobs);
|
|
66
47
|
this.cache.set(nodeId, executionInfo);
|
|
67
48
|
return executionInfo;
|
|
68
49
|
}
|
|
@@ -74,7 +55,7 @@ export class NodeExecutionService {
|
|
|
74
55
|
/**
|
|
75
56
|
* Get execution information for multiple nodes from pipeline data
|
|
76
57
|
*/
|
|
77
|
-
async getMultipleNodeExecutionInfo(nodeIds, pipelineId) {
|
|
58
|
+
async getMultipleNodeExecutionInfo(endpointConfig, nodeIds, pipelineId) {
|
|
78
59
|
if (!pipelineId) {
|
|
79
60
|
return {};
|
|
80
61
|
}
|
|
@@ -91,7 +72,6 @@ export class NodeExecutionService {
|
|
|
91
72
|
return defaultExecutionInfo;
|
|
92
73
|
}
|
|
93
74
|
try {
|
|
94
|
-
const endpointConfig = getEndpointConfig();
|
|
95
75
|
if (!endpointConfig)
|
|
96
76
|
throw new Error('Endpoint config not available');
|
|
97
77
|
const url = buildEndpointUrl(endpointConfig, endpointConfig.endpoints.pipelines.get, {
|
|
@@ -120,28 +100,11 @@ export class NodeExecutionService {
|
|
|
120
100
|
const raw = await response.json();
|
|
121
101
|
const result = raw.data ?? raw;
|
|
122
102
|
const jobs = result.jobs || [];
|
|
103
|
+
const nodeStatuses = result.node_statuses || {};
|
|
123
104
|
const executionInfoMap = {};
|
|
124
|
-
// Initialize all nodes with default values
|
|
125
105
|
nodeIds.forEach((nodeId) => {
|
|
126
|
-
executionInfoMap[nodeId] =
|
|
127
|
-
|
|
128
|
-
executionCount: 0,
|
|
129
|
-
isExecuting: false
|
|
130
|
-
};
|
|
131
|
-
});
|
|
132
|
-
// Update with actual job data
|
|
133
|
-
jobs.forEach((job) => {
|
|
134
|
-
const nodeId = job.node_id;
|
|
135
|
-
if (nodeIds.includes(nodeId)) {
|
|
136
|
-
executionInfoMap[nodeId] = {
|
|
137
|
-
status: this.mapJobStatusToExecutionStatus(job.status),
|
|
138
|
-
executionCount: job.execution_count || 0,
|
|
139
|
-
isExecuting: job.status === 'running',
|
|
140
|
-
lastExecuted: job.completed || job.started,
|
|
141
|
-
lastExecutionDuration: job.execution_time,
|
|
142
|
-
lastError: job.error_message
|
|
143
|
-
};
|
|
144
|
-
// Update cache
|
|
106
|
+
executionInfoMap[nodeId] = this.buildNodeExecutionInfo(nodeId, nodeStatuses[nodeId], jobs);
|
|
107
|
+
if (executionInfoMap[nodeId].status !== 'idle' || executionInfoMap[nodeId].jobs) {
|
|
145
108
|
this.cache.set(nodeId, executionInfoMap[nodeId]);
|
|
146
109
|
}
|
|
147
110
|
});
|
|
@@ -164,9 +127,8 @@ export class NodeExecutionService {
|
|
|
164
127
|
/**
|
|
165
128
|
* Get all node execution counts
|
|
166
129
|
*/
|
|
167
|
-
async getAllNodeExecutionCounts() {
|
|
130
|
+
async getAllNodeExecutionCounts(endpointConfig) {
|
|
168
131
|
try {
|
|
169
|
-
const endpointConfig = getEndpointConfig();
|
|
170
132
|
if (!endpointConfig)
|
|
171
133
|
throw new Error('Endpoint config not available');
|
|
172
134
|
const url = buildEndpointUrl(endpointConfig, '/node-execution-counts');
|
|
@@ -227,6 +189,66 @@ export class NodeExecutionService {
|
|
|
227
189
|
});
|
|
228
190
|
}
|
|
229
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* Build execution info for one node from the pipeline payload.
|
|
194
|
+
*
|
|
195
|
+
* The `node_statuses` entry is the backend-resolved summary (latest job's
|
|
196
|
+
* status, timing from the most recent run, `executions` count); the per-job
|
|
197
|
+
* history is attached from the `jobs` array so loop iterations stay
|
|
198
|
+
* inspectable. Falls back to the node's jobs when no entry exists (older
|
|
199
|
+
* backends).
|
|
200
|
+
*/
|
|
201
|
+
buildNodeExecutionInfo(nodeId, entry, jobs) {
|
|
202
|
+
const nodeJobs = jobs.filter((job) => job.node_id === nodeId);
|
|
203
|
+
if (!entry && nodeJobs.length === 0) {
|
|
204
|
+
return {
|
|
205
|
+
status: 'idle',
|
|
206
|
+
executionCount: 0,
|
|
207
|
+
isExecuting: false
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
// Fallback for payloads without a node_statuses entry: the last job in
|
|
211
|
+
// pipeline order mirrors the backend's latest-wins resolution.
|
|
212
|
+
const lastJob = nodeJobs[nodeJobs.length - 1];
|
|
213
|
+
const status = entry?.status ?? lastJob?.status ?? 'idle';
|
|
214
|
+
const startedCount = nodeJobs.filter((job) => job.started).length;
|
|
215
|
+
const executionInfo = {
|
|
216
|
+
status: this.mapJobStatusToExecutionStatus(status),
|
|
217
|
+
executionCount: entry?.executions ?? startedCount,
|
|
218
|
+
isExecuting: status === 'running' || nodeJobs.some((job) => job.status === 'running'),
|
|
219
|
+
lastExecuted: entry?.last_executed ?? lastJob?.completed ?? lastJob?.started ?? undefined,
|
|
220
|
+
lastExecutionDuration: entry?.execution_time ?? lastJob?.execution_time ?? undefined,
|
|
221
|
+
lastExecutionDurationUs: entry?.execution_time_us ?? lastJob?.execution_time_us ?? undefined,
|
|
222
|
+
lastError: entry?.error ?? lastJob?.error_message ?? undefined
|
|
223
|
+
};
|
|
224
|
+
if (nodeJobs.length > 0) {
|
|
225
|
+
executionInfo.jobs = nodeJobs.map((job) => this.mapJobToNodeJobExecution(job));
|
|
226
|
+
}
|
|
227
|
+
return executionInfo;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Map a pipeline job payload entry to a NodeJobExecution history item.
|
|
231
|
+
*/
|
|
232
|
+
mapJobToNodeJobExecution(job) {
|
|
233
|
+
let executionTime = job.execution_time;
|
|
234
|
+
if (executionTime == null && job.started && job.completed) {
|
|
235
|
+
const started = Date.parse(job.started);
|
|
236
|
+
const completed = Date.parse(job.completed);
|
|
237
|
+
if (!Number.isNaN(started) && !Number.isNaN(completed)) {
|
|
238
|
+
executionTime = completed - started;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
id: job.id,
|
|
243
|
+
label: job.label,
|
|
244
|
+
status: this.mapJobStatusToExecutionStatus(job.status),
|
|
245
|
+
started: job.started,
|
|
246
|
+
completed: job.completed,
|
|
247
|
+
executionTime,
|
|
248
|
+
executionTimeUs: job.execution_time_us ?? (executionTime != null ? executionTime * 1000 : undefined),
|
|
249
|
+
error: job.error_message ?? job.error
|
|
250
|
+
};
|
|
251
|
+
}
|
|
230
252
|
/**
|
|
231
253
|
* Map job status to execution status
|
|
232
254
|
*/
|
|
@@ -244,6 +266,10 @@ export class NodeExecutionService {
|
|
|
244
266
|
return 'cancelled';
|
|
245
267
|
case 'skipped':
|
|
246
268
|
return 'skipped';
|
|
269
|
+
case 'paused':
|
|
270
|
+
return 'paused';
|
|
271
|
+
case 'interrupted':
|
|
272
|
+
return 'interrupted';
|
|
247
273
|
default:
|
|
248
274
|
return 'idle';
|
|
249
275
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* @module services/playgroundService
|
|
8
8
|
*/
|
|
9
9
|
import type { PlaygroundSession, PlaygroundMessage, PlaygroundMessagesApiResponse, PlaygroundSessionStatus } from '../types/playground.js';
|
|
10
|
+
import type { EndpointConfig } from '../config/endpoints.js';
|
|
10
11
|
/**
|
|
11
12
|
* Pagination options for {@link PlaygroundService.getMessages}.
|
|
12
13
|
* `since`, `before`, and `latest` are mutually exclusive.
|
|
@@ -41,7 +42,10 @@ export declare class PlaygroundService {
|
|
|
41
42
|
*/
|
|
42
43
|
static getInstance(): PlaygroundService;
|
|
43
44
|
/**
|
|
44
|
-
*
|
|
45
|
+
* Validate and return the endpoint configuration passed by the caller.
|
|
46
|
+
*
|
|
47
|
+
* Callers thread the config from `getInstance().api.config`; this enforces
|
|
48
|
+
* the legacy "throws if not configured" contract.
|
|
45
49
|
*
|
|
46
50
|
* @throws Error if endpoint configuration is not set
|
|
47
51
|
* @returns The endpoint configuration
|
|
@@ -50,6 +54,7 @@ export declare class PlaygroundService {
|
|
|
50
54
|
/**
|
|
51
55
|
* Generic API request helper
|
|
52
56
|
*
|
|
57
|
+
* @param config - The endpoint configuration
|
|
53
58
|
* @param url - The URL to fetch
|
|
54
59
|
* @param options - Fetch options
|
|
55
60
|
* @returns The parsed JSON response
|
|
@@ -62,7 +67,7 @@ export declare class PlaygroundService {
|
|
|
62
67
|
* @param options - Optional pagination parameters
|
|
63
68
|
* @returns Array of playground sessions
|
|
64
69
|
*/
|
|
65
|
-
listSessions(workflowId: string, options?: {
|
|
70
|
+
listSessions(endpointConfig: EndpointConfig | null, workflowId: string, options?: {
|
|
66
71
|
limit?: number;
|
|
67
72
|
offset?: number;
|
|
68
73
|
}): Promise<PlaygroundSession[]>;
|
|
@@ -74,20 +79,20 @@ export declare class PlaygroundService {
|
|
|
74
79
|
* @param metadata - Optional session metadata
|
|
75
80
|
* @returns The created session
|
|
76
81
|
*/
|
|
77
|
-
createSession(workflowId: string, name?: string, metadata?: Record<string, unknown>): Promise<PlaygroundSession>;
|
|
82
|
+
createSession(endpointConfig: EndpointConfig | null, workflowId: string, name?: string, metadata?: Record<string, unknown>): Promise<PlaygroundSession>;
|
|
78
83
|
/**
|
|
79
84
|
* Get a playground session by ID
|
|
80
85
|
*
|
|
81
86
|
* @param sessionId - The session UUID
|
|
82
87
|
* @returns The session details
|
|
83
88
|
*/
|
|
84
|
-
getSession(sessionId: string): Promise<PlaygroundSession>;
|
|
89
|
+
getSession(endpointConfig: EndpointConfig | null, sessionId: string): Promise<PlaygroundSession>;
|
|
85
90
|
/**
|
|
86
91
|
* Delete a playground session
|
|
87
92
|
*
|
|
88
93
|
* @param sessionId - The session UUID
|
|
89
94
|
*/
|
|
90
|
-
deleteSession(sessionId: string): Promise<void>;
|
|
95
|
+
deleteSession(endpointConfig: EndpointConfig | null, sessionId: string): Promise<void>;
|
|
91
96
|
/**
|
|
92
97
|
* Get messages from a playground session.
|
|
93
98
|
*
|
|
@@ -101,7 +106,7 @@ export declare class PlaygroundService {
|
|
|
101
106
|
* @param options - Pagination options
|
|
102
107
|
* @returns Messages and session status
|
|
103
108
|
*/
|
|
104
|
-
getMessages(sessionId: string, options?: GetMessagesOptions): Promise<PlaygroundMessagesApiResponse>;
|
|
109
|
+
getMessages(endpointConfig: EndpointConfig | null, sessionId: string, options?: GetMessagesOptions): Promise<PlaygroundMessagesApiResponse>;
|
|
105
110
|
/**
|
|
106
111
|
* Send a message to a playground session
|
|
107
112
|
*
|
|
@@ -110,13 +115,13 @@ export declare class PlaygroundService {
|
|
|
110
115
|
* @param inputs - Optional additional inputs for workflow nodes
|
|
111
116
|
* @returns The created message
|
|
112
117
|
*/
|
|
113
|
-
sendMessage(sessionId: string, content: string, inputs?: Record<string, unknown>): Promise<PlaygroundMessage>;
|
|
118
|
+
sendMessage(endpointConfig: EndpointConfig | null, sessionId: string, content: string, inputs?: Record<string, unknown>): Promise<PlaygroundMessage>;
|
|
114
119
|
/**
|
|
115
120
|
* Stop execution in a playground session
|
|
116
121
|
*
|
|
117
122
|
* @param sessionId - The session UUID
|
|
118
123
|
*/
|
|
119
|
-
stopExecution(sessionId: string): Promise<void>;
|
|
124
|
+
stopExecution(endpointConfig: EndpointConfig | null, sessionId: string): Promise<void>;
|
|
120
125
|
/**
|
|
121
126
|
* Start polling for new messages
|
|
122
127
|
*
|
|
@@ -126,7 +131,7 @@ export declare class PlaygroundService {
|
|
|
126
131
|
* @param shouldStopPolling - Optional override for stop conditions (default: defaultShouldStopPolling)
|
|
127
132
|
* @param initialSequenceNumber - Optional sequence number to seed polling from (avoids re-fetching already loaded messages)
|
|
128
133
|
*/
|
|
129
|
-
startPolling(sessionId: string, callback: (response: PlaygroundMessagesApiResponse) => void, interval?: number, shouldStopPolling?: (status: PlaygroundSessionStatus) => boolean, initialSequenceNumber?: number | null): void;
|
|
134
|
+
startPolling(endpointConfig: EndpointConfig | null, sessionId: string, callback: (response: PlaygroundMessagesApiResponse) => void, interval?: number, shouldStopPolling?: (status: PlaygroundSessionStatus) => boolean, initialSequenceNumber?: number | null): void;
|
|
130
135
|
/**
|
|
131
136
|
* Stop polling for messages
|
|
132
137
|
*/
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { defaultShouldStopPolling } from '../types/playground.js';
|
|
10
10
|
import { buildEndpointUrl, getEndpointHeaders } from '../config/endpoints.js';
|
|
11
|
-
import { getEndpointConfig } from './api.js';
|
|
12
11
|
import { logger } from '../utils/logger.js';
|
|
13
12
|
/**
|
|
14
13
|
* Default polling interval in milliseconds
|
|
@@ -43,27 +42,29 @@ export class PlaygroundService {
|
|
|
43
42
|
return PlaygroundService.instance;
|
|
44
43
|
}
|
|
45
44
|
/**
|
|
46
|
-
*
|
|
45
|
+
* Validate and return the endpoint configuration passed by the caller.
|
|
46
|
+
*
|
|
47
|
+
* Callers thread the config from `getInstance().api.config`; this enforces
|
|
48
|
+
* the legacy "throws if not configured" contract.
|
|
47
49
|
*
|
|
48
50
|
* @throws Error if endpoint configuration is not set
|
|
49
51
|
* @returns The endpoint configuration
|
|
50
52
|
*/
|
|
51
|
-
getConfig() {
|
|
52
|
-
const config = getEndpointConfig();
|
|
53
|
+
getConfig(config) {
|
|
53
54
|
if (!config) {
|
|
54
|
-
throw new Error('Endpoint configuration not set.
|
|
55
|
+
throw new Error('Endpoint configuration not set. Configure the instance via fd.api.configure().');
|
|
55
56
|
}
|
|
56
57
|
return config;
|
|
57
58
|
}
|
|
58
59
|
/**
|
|
59
60
|
* Generic API request helper
|
|
60
61
|
*
|
|
62
|
+
* @param config - The endpoint configuration
|
|
61
63
|
* @param url - The URL to fetch
|
|
62
64
|
* @param options - Fetch options
|
|
63
65
|
* @returns The parsed JSON response
|
|
64
66
|
*/
|
|
65
|
-
async request(url, options = {}) {
|
|
66
|
-
const config = this.getConfig();
|
|
67
|
+
async request(config, url, options = {}) {
|
|
67
68
|
const headers = getEndpointHeaders(config, 'playground');
|
|
68
69
|
const response = await fetch(url, {
|
|
69
70
|
...options,
|
|
@@ -91,8 +92,8 @@ export class PlaygroundService {
|
|
|
91
92
|
* @param options - Optional pagination parameters
|
|
92
93
|
* @returns Array of playground sessions
|
|
93
94
|
*/
|
|
94
|
-
async listSessions(workflowId, options) {
|
|
95
|
-
const config = this.getConfig();
|
|
95
|
+
async listSessions(endpointConfig, workflowId, options) {
|
|
96
|
+
const config = this.getConfig(endpointConfig);
|
|
96
97
|
let url = buildEndpointUrl(config, config.endpoints.playground.listSessions, {
|
|
97
98
|
id: workflowId
|
|
98
99
|
});
|
|
@@ -108,7 +109,7 @@ export class PlaygroundService {
|
|
|
108
109
|
if (queryString) {
|
|
109
110
|
url = `${url}?${queryString}`;
|
|
110
111
|
}
|
|
111
|
-
const response = await this.request(url);
|
|
112
|
+
const response = await this.request(config, url);
|
|
112
113
|
return response.data ?? [];
|
|
113
114
|
}
|
|
114
115
|
/**
|
|
@@ -119,12 +120,12 @@ export class PlaygroundService {
|
|
|
119
120
|
* @param metadata - Optional session metadata
|
|
120
121
|
* @returns The created session
|
|
121
122
|
*/
|
|
122
|
-
async createSession(workflowId, name, metadata) {
|
|
123
|
-
const config = this.getConfig();
|
|
123
|
+
async createSession(endpointConfig, workflowId, name, metadata) {
|
|
124
|
+
const config = this.getConfig(endpointConfig);
|
|
124
125
|
const url = buildEndpointUrl(config, config.endpoints.playground.createSession, {
|
|
125
126
|
id: workflowId
|
|
126
127
|
});
|
|
127
|
-
const response = await this.request(url, {
|
|
128
|
+
const response = await this.request(config, url, {
|
|
128
129
|
method: 'POST',
|
|
129
130
|
body: JSON.stringify({ name, metadata })
|
|
130
131
|
});
|
|
@@ -139,12 +140,12 @@ export class PlaygroundService {
|
|
|
139
140
|
* @param sessionId - The session UUID
|
|
140
141
|
* @returns The session details
|
|
141
142
|
*/
|
|
142
|
-
async getSession(sessionId) {
|
|
143
|
-
const config = this.getConfig();
|
|
143
|
+
async getSession(endpointConfig, sessionId) {
|
|
144
|
+
const config = this.getConfig(endpointConfig);
|
|
144
145
|
const url = buildEndpointUrl(config, config.endpoints.playground.getSession, {
|
|
145
146
|
sessionId
|
|
146
147
|
});
|
|
147
|
-
const response = await this.request(url);
|
|
148
|
+
const response = await this.request(config, url);
|
|
148
149
|
if (!response.data) {
|
|
149
150
|
throw new Error('Session not found');
|
|
150
151
|
}
|
|
@@ -155,12 +156,12 @@ export class PlaygroundService {
|
|
|
155
156
|
*
|
|
156
157
|
* @param sessionId - The session UUID
|
|
157
158
|
*/
|
|
158
|
-
async deleteSession(sessionId) {
|
|
159
|
-
const config = this.getConfig();
|
|
159
|
+
async deleteSession(endpointConfig, sessionId) {
|
|
160
|
+
const config = this.getConfig(endpointConfig);
|
|
160
161
|
const url = buildEndpointUrl(config, config.endpoints.playground.deleteSession, {
|
|
161
162
|
sessionId
|
|
162
163
|
});
|
|
163
|
-
await this.request(url, {
|
|
164
|
+
await this.request(config, url, {
|
|
164
165
|
method: 'DELETE'
|
|
165
166
|
});
|
|
166
167
|
}
|
|
@@ -180,8 +181,8 @@ export class PlaygroundService {
|
|
|
180
181
|
* @param options - Pagination options
|
|
181
182
|
* @returns Messages and session status
|
|
182
183
|
*/
|
|
183
|
-
async getMessages(sessionId, options = {}) {
|
|
184
|
-
const config = this.getConfig();
|
|
184
|
+
async getMessages(endpointConfig, sessionId, options = {}) {
|
|
185
|
+
const config = this.getConfig(endpointConfig);
|
|
185
186
|
let url = buildEndpointUrl(config, config.endpoints.playground.getMessages, {
|
|
186
187
|
sessionId
|
|
187
188
|
});
|
|
@@ -202,7 +203,7 @@ export class PlaygroundService {
|
|
|
202
203
|
if (queryString) {
|
|
203
204
|
url = `${url}?${queryString}`;
|
|
204
205
|
}
|
|
205
|
-
return this.request(url);
|
|
206
|
+
return this.request(config, url);
|
|
206
207
|
}
|
|
207
208
|
/**
|
|
208
209
|
* Send a message to a playground session
|
|
@@ -212,8 +213,8 @@ export class PlaygroundService {
|
|
|
212
213
|
* @param inputs - Optional additional inputs for workflow nodes
|
|
213
214
|
* @returns The created message
|
|
214
215
|
*/
|
|
215
|
-
async sendMessage(sessionId, content, inputs) {
|
|
216
|
-
const config = this.getConfig();
|
|
216
|
+
async sendMessage(endpointConfig, sessionId, content, inputs) {
|
|
217
|
+
const config = this.getConfig(endpointConfig);
|
|
217
218
|
const url = buildEndpointUrl(config, config.endpoints.playground.sendMessage, {
|
|
218
219
|
sessionId
|
|
219
220
|
});
|
|
@@ -221,7 +222,7 @@ export class PlaygroundService {
|
|
|
221
222
|
if (inputs) {
|
|
222
223
|
requestBody.inputs = inputs;
|
|
223
224
|
}
|
|
224
|
-
const response = await this.request(url, {
|
|
225
|
+
const response = await this.request(config, url, {
|
|
225
226
|
method: 'POST',
|
|
226
227
|
body: JSON.stringify(requestBody)
|
|
227
228
|
});
|
|
@@ -235,12 +236,12 @@ export class PlaygroundService {
|
|
|
235
236
|
*
|
|
236
237
|
* @param sessionId - The session UUID
|
|
237
238
|
*/
|
|
238
|
-
async stopExecution(sessionId) {
|
|
239
|
-
const config = this.getConfig();
|
|
239
|
+
async stopExecution(endpointConfig, sessionId) {
|
|
240
|
+
const config = this.getConfig(endpointConfig);
|
|
240
241
|
const url = buildEndpointUrl(config, config.endpoints.playground.stopExecution, {
|
|
241
242
|
sessionId
|
|
242
243
|
});
|
|
243
|
-
await this.request(url, {
|
|
244
|
+
await this.request(config, url, {
|
|
244
245
|
method: 'POST'
|
|
245
246
|
});
|
|
246
247
|
}
|
|
@@ -256,7 +257,7 @@ export class PlaygroundService {
|
|
|
256
257
|
* @param shouldStopPolling - Optional override for stop conditions (default: defaultShouldStopPolling)
|
|
257
258
|
* @param initialSequenceNumber - Optional sequence number to seed polling from (avoids re-fetching already loaded messages)
|
|
258
259
|
*/
|
|
259
|
-
startPolling(sessionId, callback, interval = DEFAULT_POLLING_INTERVAL, shouldStopPolling, initialSequenceNumber) {
|
|
260
|
+
startPolling(endpointConfig, sessionId, callback, interval = DEFAULT_POLLING_INTERVAL, shouldStopPolling, initialSequenceNumber) {
|
|
260
261
|
// Stop any existing polling
|
|
261
262
|
this.stopPolling();
|
|
262
263
|
this.pollingSessionId = sessionId;
|
|
@@ -268,7 +269,7 @@ export class PlaygroundService {
|
|
|
268
269
|
return;
|
|
269
270
|
}
|
|
270
271
|
try {
|
|
271
|
-
const response = await this.getMessages(sessionId, {
|
|
272
|
+
const response = await this.getMessages(endpointConfig, sessionId, {
|
|
272
273
|
since: this.lastSequenceNumber ?? undefined
|
|
273
274
|
});
|
|
274
275
|
// Update last sequence number cursor
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* @module services/variableService
|
|
7
7
|
*/
|
|
8
8
|
import type { WorkflowNode, WorkflowEdge, VariableSchema, TemplateVariable, TemplateVariablesConfig, AuthProvider } from '../types/index.js';
|
|
9
|
+
import type { EndpointConfig } from '../config/endpoints.js';
|
|
9
10
|
/**
|
|
10
11
|
* Options for deriving available variables.
|
|
11
12
|
*/
|
|
@@ -138,4 +139,4 @@ export declare function mergeVariableSchemas(primary: VariableSchema, secondary:
|
|
|
138
139
|
* const schema = await getVariableSchema(node, nodes, edges, config, workflowId, authProvider);
|
|
139
140
|
* ```
|
|
140
141
|
*/
|
|
141
|
-
export declare function getVariableSchema(node: WorkflowNode, nodes: WorkflowNode[], edges: WorkflowEdge[], config: TemplateVariablesConfig, workflowId?: string, authProvider?: AuthProvider): Promise<VariableSchema>;
|
|
142
|
+
export declare function getVariableSchema(endpointConfig: EndpointConfig | null, node: WorkflowNode, nodes: WorkflowNode[], edges: WorkflowEdge[], config: TemplateVariablesConfig, workflowId?: string, authProvider?: AuthProvider): Promise<VariableSchema>;
|
|
@@ -405,14 +405,14 @@ export function mergeVariableSchemas(primary, secondary) {
|
|
|
405
405
|
* const schema = await getVariableSchema(node, nodes, edges, config, workflowId, authProvider);
|
|
406
406
|
* ```
|
|
407
407
|
*/
|
|
408
|
-
export async function getVariableSchema(node, nodes, edges, config, workflowId, authProvider) {
|
|
408
|
+
export async function getVariableSchema(endpointConfig, node, nodes, edges, config, workflowId, authProvider) {
|
|
409
409
|
let resultSchema = { variables: {} };
|
|
410
410
|
// Try API mode first (if configured)
|
|
411
411
|
if (config.api) {
|
|
412
412
|
try {
|
|
413
413
|
// Import API variable service dynamically to avoid circular dependencies
|
|
414
414
|
const { fetchVariableSchema } = await import('./apiVariableService.js');
|
|
415
|
-
const apiResult = await fetchVariableSchema(workflowId, node.id, config.api, authProvider);
|
|
415
|
+
const apiResult = await fetchVariableSchema(endpointConfig, workflowId, node.id, config.api, authProvider);
|
|
416
416
|
if (apiResult.success && apiResult.schema) {
|
|
417
417
|
resultSchema = apiResult.schema;
|
|
418
418
|
// Merge with static schema if configured
|
|
@@ -20,10 +20,10 @@ export async function saveWorkflow(workflow) {
|
|
|
20
20
|
...workflow,
|
|
21
21
|
id,
|
|
22
22
|
metadata: {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
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
|
-
|
|
108
|
+
schemaVersion: '1.0.0',
|
|
109
109
|
createdAt: new Date().toISOString(),
|
|
110
110
|
updatedAt: new Date().toISOString(),
|
|
111
111
|
author: 'System',
|
|
@@ -0,0 +1,45 @@
|
|
|
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
|
+
/** Whether {@link configure} has been called with a usable config. */
|
|
44
|
+
isConfigured(): boolean;
|
|
45
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
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
|
+
/** Whether {@link configure} has been called with a usable config. */
|
|
62
|
+
isConfigured() {
|
|
63
|
+
return Boolean(this.#config);
|
|
64
|
+
}
|
|
65
|
+
}
|