@mesantosrai/pipeline-canvas 1.0.0

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 (148) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +545 -0
  3. package/dist/_virtual/dynamic-import-helper.mjs +17 -0
  4. package/dist/_virtual/dynamic-import-helper.mjs.map +1 -0
  5. package/dist/components/CustomHandle.d.ts +9 -0
  6. package/dist/components/CustomHandle.d.ts.map +1 -0
  7. package/dist/components/CustomHandle.mjs +18 -0
  8. package/dist/components/CustomHandle.mjs.map +1 -0
  9. package/dist/components/ExecutionLogsPanel.d.ts +3 -0
  10. package/dist/components/ExecutionLogsPanel.d.ts.map +1 -0
  11. package/dist/components/ExecutionLogsPanel.mjs +189 -0
  12. package/dist/components/ExecutionLogsPanel.mjs.map +1 -0
  13. package/dist/components/NodeContextMenu.d.ts +15 -0
  14. package/dist/components/NodeContextMenu.d.ts.map +1 -0
  15. package/dist/components/NodeContextMenu.mjs +110 -0
  16. package/dist/components/NodeContextMenu.mjs.map +1 -0
  17. package/dist/components/PipelineCanvas.d.ts +4 -0
  18. package/dist/components/PipelineCanvas.d.ts.map +1 -0
  19. package/dist/components/PipelineCanvas.mjs +1016 -0
  20. package/dist/components/PipelineCanvas.mjs.map +1 -0
  21. package/dist/components/PipelineCanvasProvider.d.ts +30 -0
  22. package/dist/components/PipelineCanvasProvider.d.ts.map +1 -0
  23. package/dist/components/PipelineCanvasProvider.mjs +7 -0
  24. package/dist/components/PipelineCanvasProvider.mjs.map +1 -0
  25. package/dist/components/PipelineExecution.d.ts +16 -0
  26. package/dist/components/PipelineExecution.d.ts.map +1 -0
  27. package/dist/components/PipelineExecution.mjs +310 -0
  28. package/dist/components/PipelineExecution.mjs.map +1 -0
  29. package/dist/components/PipelineManager.d.ts +8 -0
  30. package/dist/components/PipelineManager.d.ts.map +1 -0
  31. package/dist/components/PipelineManager.mjs +143 -0
  32. package/dist/components/PipelineManager.mjs.map +1 -0
  33. package/dist/components/PipelineNodeConfig.d.ts +11 -0
  34. package/dist/components/PipelineNodeConfig.d.ts.map +1 -0
  35. package/dist/components/PipelineNodeConfig.mjs +1808 -0
  36. package/dist/components/PipelineNodeConfig.mjs.map +1 -0
  37. package/dist/components/PipelineNodePalette.d.ts +3 -0
  38. package/dist/components/PipelineNodePalette.d.ts.map +1 -0
  39. package/dist/components/PipelineNodePalette.mjs +87 -0
  40. package/dist/components/PipelineNodePalette.mjs.map +1 -0
  41. package/dist/components/SavePipelineDialog.d.ts +9 -0
  42. package/dist/components/SavePipelineDialog.d.ts.map +1 -0
  43. package/dist/components/SavePipelineDialog.mjs +140 -0
  44. package/dist/components/SavePipelineDialog.mjs.map +1 -0
  45. package/dist/components/SavedPipelinesList.d.ts +3 -0
  46. package/dist/components/SavedPipelinesList.d.ts.map +1 -0
  47. package/dist/components/SavedPipelinesList.mjs +172 -0
  48. package/dist/components/SavedPipelinesList.mjs.map +1 -0
  49. package/dist/components/index.d.ts +8 -0
  50. package/dist/components/index.d.ts.map +1 -0
  51. package/dist/components/ui/alert.d.ts +9 -0
  52. package/dist/components/ui/alert.d.ts.map +1 -0
  53. package/dist/components/ui/alert.mjs +51 -0
  54. package/dist/components/ui/alert.mjs.map +1 -0
  55. package/dist/components/ui/button.d.ts +12 -0
  56. package/dist/components/ui/button.d.ts.map +1 -0
  57. package/dist/components/ui/button.mjs +45 -0
  58. package/dist/components/ui/button.mjs.map +1 -0
  59. package/dist/components/ui/dialog.d.ts +20 -0
  60. package/dist/components/ui/dialog.d.ts.map +1 -0
  61. package/dist/components/ui/dialog.mjs +99 -0
  62. package/dist/components/ui/dialog.mjs.map +1 -0
  63. package/dist/components/ui/index.d.ts +8 -0
  64. package/dist/components/ui/index.d.ts.map +1 -0
  65. package/dist/components/ui/input.d.ts +6 -0
  66. package/dist/components/ui/input.d.ts.map +1 -0
  67. package/dist/components/ui/input.mjs +22 -0
  68. package/dist/components/ui/input.mjs.map +1 -0
  69. package/dist/components/ui/label.d.ts +6 -0
  70. package/dist/components/ui/label.d.ts.map +1 -0
  71. package/dist/components/ui/label.mjs +20 -0
  72. package/dist/components/ui/label.mjs.map +1 -0
  73. package/dist/components/ui/select.d.ts +14 -0
  74. package/dist/components/ui/select.d.ts.map +1 -0
  75. package/dist/components/ui/select.mjs +121 -0
  76. package/dist/components/ui/select.mjs.map +1 -0
  77. package/dist/components/ui/tooltip.d.ts +8 -0
  78. package/dist/components/ui/tooltip.d.ts.map +1 -0
  79. package/dist/components/ui/tooltip.mjs +24 -0
  80. package/dist/components/ui/tooltip.mjs.map +1 -0
  81. package/dist/context/PipelineContext.d.ts +50 -0
  82. package/dist/context/PipelineContext.d.ts.map +1 -0
  83. package/dist/context/PipelineContext.mjs +36 -0
  84. package/dist/context/PipelineContext.mjs.map +1 -0
  85. package/dist/index.d.ts +12 -0
  86. package/dist/index.d.ts.map +1 -0
  87. package/dist/index.mjs +45 -0
  88. package/dist/index.mjs.map +1 -0
  89. package/dist/lib/utils.d.ts +3 -0
  90. package/dist/lib/utils.d.ts.map +1 -0
  91. package/dist/lib/utils.mjs +9 -0
  92. package/dist/lib/utils.mjs.map +1 -0
  93. package/dist/node_modules/zustand/esm/middleware.mjs +256 -0
  94. package/dist/node_modules/zustand/esm/middleware.mjs.map +1 -0
  95. package/dist/nodes/alphafold_node/node.json.mjs +82 -0
  96. package/dist/nodes/alphafold_node/node.json.mjs.map +1 -0
  97. package/dist/nodes/http_request_node/node.json.mjs +383 -0
  98. package/dist/nodes/http_request_node/node.json.mjs.map +1 -0
  99. package/dist/nodes/input_node/node.json.mjs +51 -0
  100. package/dist/nodes/input_node/node.json.mjs.map +1 -0
  101. package/dist/nodes/message_input_node/node.json.mjs +90 -0
  102. package/dist/nodes/message_input_node/node.json.mjs.map +1 -0
  103. package/dist/nodes/proteinmpnn_node/node.json.mjs +83 -0
  104. package/dist/nodes/proteinmpnn_node/node.json.mjs.map +1 -0
  105. package/dist/nodes/rfdiffusion_node/node.json.mjs +281 -0
  106. package/dist/nodes/rfdiffusion_node/node.json.mjs.map +1 -0
  107. package/dist/store/pipelineStore.d.ts +108 -0
  108. package/dist/store/pipelineStore.d.ts.map +1 -0
  109. package/dist/store/pipelineStore.mjs +633 -0
  110. package/dist/store/pipelineStore.mjs.map +1 -0
  111. package/dist/style.css +1 -0
  112. package/dist/types/dependencies.d.ts +93 -0
  113. package/dist/types/dependencies.d.ts.map +1 -0
  114. package/dist/types/index.d.ts +56 -0
  115. package/dist/types/index.d.ts.map +1 -0
  116. package/dist/types/logger.d.ts +67 -0
  117. package/dist/types/logger.d.ts.map +1 -0
  118. package/dist/types/logger.mjs +22 -0
  119. package/dist/types/logger.mjs.map +1 -0
  120. package/dist/utils/executionEngine.d.ts +27 -0
  121. package/dist/utils/executionEngine.d.ts.map +1 -0
  122. package/dist/utils/executionEngine.mjs +461 -0
  123. package/dist/utils/executionEngine.mjs.map +1 -0
  124. package/dist/utils/index.d.ts +6 -0
  125. package/dist/utils/index.d.ts.map +1 -0
  126. package/dist/utils/logger.d.ts +23 -0
  127. package/dist/utils/logger.d.ts.map +1 -0
  128. package/dist/utils/logger.mjs +29 -0
  129. package/dist/utils/logger.mjs.map +1 -0
  130. package/dist/utils/nodeLoader.d.ts +76 -0
  131. package/dist/utils/nodeLoader.d.ts.map +1 -0
  132. package/dist/utils/nodeLoader.mjs +48 -0
  133. package/dist/utils/nodeLoader.mjs.map +1 -0
  134. package/dist/utils/templateResolver.d.ts +10 -0
  135. package/dist/utils/templateResolver.d.ts.map +1 -0
  136. package/dist/utils/templateResolver.mjs +64 -0
  137. package/dist/utils/templateResolver.mjs.map +1 -0
  138. package/dist/utils/topologicalSort.d.ts +10 -0
  139. package/dist/utils/topologicalSort.d.ts.map +1 -0
  140. package/dist/utils/topologicalSort.mjs +25 -0
  141. package/dist/utils/topologicalSort.mjs.map +1 -0
  142. package/nodes/alphafold_node/node.json +77 -0
  143. package/nodes/http_request_node/node.json +311 -0
  144. package/nodes/input_node/node.json +47 -0
  145. package/nodes/message_input_node/node.json +56 -0
  146. package/nodes/proteinmpnn_node/node.json +78 -0
  147. package/nodes/rfdiffusion_node/node.json +231 -0
  148. package/package.json +94 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 NovoProtein AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,545 @@
1
+ # @novoprotein/pipeline-canvas
2
+
3
+ A React component library for building visual pipeline/workflow canvases using React Flow.
4
+
5
+ ## Installation from Private GitHub Repo
6
+
7
+ ### Using SSH (Recommended for Private Repos)
8
+
9
+ ```bash
10
+ npm install git+ssh://git@github.com:santosrai/pipeline-canvas.git
11
+ ```
12
+
13
+ ### Using HTTPS with Personal Access Token
14
+
15
+ ```bash
16
+ npm install git+https://YOUR_TOKEN@github.com/santosrai/pipeline-canvas.git
17
+ ```
18
+
19
+ ### Using Specific Branch or Tag
20
+
21
+ ```bash
22
+ npm install git+ssh://git@github.com:santosrai/pipeline-canvas.git#main
23
+ npm install git+ssh://git@github.com:santosrai/pipeline-canvas.git#v1.0.0
24
+ ```
25
+
26
+ ## Setup
27
+
28
+ 1. Install dependencies:
29
+ ```bash
30
+ npm install
31
+ ```
32
+
33
+ 2. Build the library:
34
+ ```bash
35
+ npm run build
36
+ ```
37
+
38
+ ## Peer Dependencies
39
+
40
+ Make sure you have these installed in your consuming project:
41
+
42
+ ```bash
43
+ npm install react react-dom reactflow zustand lucide-react
44
+ ```
45
+
46
+ ### shadcn/ui Components (Required)
47
+
48
+ This library uses shadcn/ui components. You need to install the required Radix UI packages and utilities:
49
+
50
+ ```bash
51
+ npm install @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-label @radix-ui/react-select @radix-ui/react-slot @radix-ui/react-tooltip class-variance-authority clsx tailwind-merge
52
+ ```
53
+
54
+ **Note**: The library includes shadcn component implementations in `components/ui/`, but you must install the peer dependencies above for them to work.
55
+
56
+ ## Usage
57
+
58
+ ### Basic Example (Standalone - No Dependencies)
59
+
60
+ The library works completely standalone without any dependencies:
61
+
62
+ ```tsx
63
+ import { PipelineCanvas, PipelineCanvasProvider } from '@novoprotein/pipeline-canvas';
64
+ import '@novoprotein/pipeline-canvas/style.css';
65
+
66
+ function App() {
67
+ return (
68
+ <PipelineCanvasProvider>
69
+ <div style={{ width: '100vw', height: '100vh' }}>
70
+ <PipelineCanvas />
71
+ </div>
72
+ </PipelineCanvasProvider>
73
+ );
74
+ }
75
+ ```
76
+
77
+ **Note**: Without dependencies, the library works in "offline mode":
78
+ - Pipelines are saved locally (localStorage)
79
+ - No backend sync
80
+ - No authentication required
81
+ - File uploads work if your API supports unauthenticated requests
82
+
83
+ ### With Authentication and API Client
84
+
85
+ For full functionality (backend sync, authenticated operations):
86
+
87
+ ```tsx
88
+ import {
89
+ PipelineCanvas,
90
+ PipelineCanvasProvider,
91
+ type ApiClient,
92
+ type AuthState
93
+ } from '@novoprotein/pipeline-canvas';
94
+ import '@novoprotein/pipeline-canvas/style.css';
95
+
96
+ function App() {
97
+ // Your API client (compatible with axios, fetch, or custom)
98
+ const apiClient: ApiClient = {
99
+ get: async (url: string) => {
100
+ const response = await fetch(`/api${url}`, {
101
+ headers: { 'Authorization': `Bearer ${token}` }
102
+ });
103
+ return { data: await response.json() };
104
+ },
105
+ post: async (url: string, data: any) => {
106
+ const response = await fetch(`/api${url}`, {
107
+ method: 'POST',
108
+ headers: {
109
+ 'Content-Type': 'application/json',
110
+ 'Authorization': `Bearer ${token}`
111
+ },
112
+ body: JSON.stringify(data)
113
+ });
114
+ return { data: await response.json() };
115
+ },
116
+ };
117
+
118
+ // Your auth state
119
+ const authState: AuthState = {
120
+ user: { id: 'user-123', email: 'user@example.com' },
121
+ isAuthenticated: true,
122
+ accessToken: token,
123
+ };
124
+
125
+ // Session ID for execution context
126
+ const sessionId = 'session-456';
127
+
128
+ // Auth headers function for file uploads
129
+ const getAuthHeaders = () => ({
130
+ 'Authorization': `Bearer ${token}`
131
+ });
132
+
133
+ return (
134
+ <PipelineCanvasProvider
135
+ apiClient={apiClient}
136
+ authState={authState}
137
+ sessionId={sessionId}
138
+ getAuthHeaders={getAuthHeaders}
139
+ >
140
+ <div style={{ width: '100vw', height: '100vh' }}>
141
+ <PipelineCanvas />
142
+ </div>
143
+ </PipelineCanvasProvider>
144
+ );
145
+ }
146
+ ```
147
+
148
+ ### With Axios API Client
149
+
150
+ If you're using axios:
151
+
152
+ ```tsx
153
+ import axios from 'axios';
154
+ import { PipelineCanvasProvider, type ApiClient } from '@novoprotein/pipeline-canvas';
155
+
156
+ const apiClient: ApiClient = {
157
+ get: (url: string, config?) => axios.get(url, config),
158
+ post: (url: string, data?: any, config?) => axios.post(url, data, config),
159
+ put: (url: string, data?: any, config?) => axios.put(url, data, config),
160
+ patch: (url: string, data?: any, config?) => axios.patch(url, data, config),
161
+ delete: (url: string, config?) => axios.delete(url, config),
162
+ };
163
+
164
+ function App() {
165
+ return (
166
+ <PipelineCanvasProvider apiClient={apiClient}>
167
+ <PipelineCanvas />
168
+ </PipelineCanvasProvider>
169
+ );
170
+ }
171
+ ```
172
+
173
+ ### Partial Dependencies
174
+
175
+ You can provide only the dependencies you need:
176
+
177
+ ```tsx
178
+ // Only API client (no auth)
179
+ <PipelineCanvasProvider apiClient={myApiClient}>
180
+ <PipelineCanvas />
181
+ </PipelineCanvasProvider>
182
+
183
+ // Only auth state (local operations only)
184
+ <PipelineCanvasProvider authState={authState}>
185
+ <PipelineCanvas />
186
+ </PipelineCanvasProvider>
187
+
188
+ // Everything optional - works standalone
189
+ <PipelineCanvasProvider>
190
+ <PipelineCanvas />
191
+ </PipelineCanvasProvider>
192
+ ```
193
+
194
+ ### Using the Store
195
+
196
+ ```tsx
197
+ import { usePipelineStore } from '@novoprotein/pipeline-canvas';
198
+
199
+ function MyComponent() {
200
+ const { nodes, edges, addNode } = usePipelineStore();
201
+
202
+ return (
203
+ <div>
204
+ <p>Nodes: {nodes.length}</p>
205
+ <button onClick={() => addNode({ id: '1', type: 'input', data: {} })}>
206
+ Add Node
207
+ </button>
208
+ </div>
209
+ );
210
+ }
211
+ ```
212
+
213
+ ### Using Context Directly
214
+
215
+ You can also access dependencies directly from context:
216
+
217
+ ```tsx
218
+ import { usePipelineContext } from '@novoprotein/pipeline-canvas';
219
+
220
+ function MyComponent() {
221
+ const { apiClient, authState, sessionId, getAuthHeaders } = usePipelineContext();
222
+
223
+ // Use dependencies as needed
224
+ if (authState?.user) {
225
+ // User is authenticated
226
+ }
227
+
228
+ return <div>...</div>;
229
+ }
230
+ ```
231
+
232
+ ## Dependency Injection
233
+
234
+ The library uses dependency injection to remain standalone and flexible. All dependencies are **optional**:
235
+
236
+ - **`apiClient`**: For backend operations (save, load, sync pipelines)
237
+ - **`authState`**: For user-specific features and authentication
238
+ - **`sessionId`**: For execution context and session tracking
239
+ - **`getAuthHeaders`**: For authenticated file uploads
240
+ - **`logger`**: For structured logging (optional, uses console by default)
241
+ - **`errorReporter`**: For error tracking (Sentry, LogRocket, etc.)
242
+
243
+ ### Graceful Degradation
244
+
245
+ When dependencies are not provided:
246
+ - ✅ Pipelines work locally (localStorage)
247
+ - ✅ All UI features work
248
+ - ✅ Pipeline execution works (with provided apiClient or external APIs)
249
+ - ⚠️ Backend sync is skipped
250
+ - ⚠️ User-specific features are disabled
251
+ - ⚠️ File uploads may fail if API requires authentication
252
+
253
+ ### Integration Examples
254
+
255
+ #### With Zustand Auth Store
256
+
257
+ ```tsx
258
+ import { useAuthStore } from './stores/authStore';
259
+ import { PipelineCanvasProvider } from '@novoprotein/pipeline-canvas';
260
+
261
+ function App() {
262
+ const user = useAuthStore(state => state.user);
263
+ const token = useAuthStore(state => state.accessToken);
264
+
265
+ const authState = {
266
+ user,
267
+ isAuthenticated: !!user,
268
+ accessToken: token,
269
+ };
270
+
271
+ return (
272
+ <PipelineCanvasProvider authState={authState}>
273
+ <PipelineCanvas />
274
+ </PipelineCanvasProvider>
275
+ );
276
+ }
277
+ ```
278
+
279
+ #### With React Context Auth
280
+
281
+ ```tsx
282
+ import { useContext } from 'react';
283
+ import { AuthContext } from './AuthContext';
284
+ import { PipelineCanvasProvider } from '@novoprotein/pipeline-canvas';
285
+
286
+ function App() {
287
+ const { user, token } = useContext(AuthContext);
288
+
289
+ return (
290
+ <PipelineCanvasProvider
291
+ authState={{ user, isAuthenticated: !!user, accessToken: token }}
292
+ >
293
+ <PipelineCanvas />
294
+ </PipelineCanvasProvider>
295
+ );
296
+ }
297
+ ```
298
+
299
+ ## Logging and Error Tracking
300
+
301
+ The library supports structured logging and error tracking through dependency injection. This allows you to integrate with your own logging systems (Sentry, LogRocket, Bugsnag, etc.) or use the default console logger.
302
+
303
+ ### Basic Usage (Default Logger)
304
+
305
+ By default, the library uses a console logger that only logs in development mode:
306
+
307
+ ```tsx
308
+ import { PipelineCanvasProvider } from '@novoprotein/pipeline-canvas';
309
+
310
+ // No logger needed - uses default console logger (development only)
311
+ <PipelineCanvasProvider>
312
+ <PipelineCanvas />
313
+ </PipelineCanvasProvider>
314
+ ```
315
+
316
+ ### Custom Logger
317
+
318
+ Provide your own logger for structured logging:
319
+
320
+ ```tsx
321
+ import {
322
+ PipelineCanvasProvider,
323
+ type Logger
324
+ } from '@novoprotein/pipeline-canvas';
325
+
326
+ const myLogger: Logger = {
327
+ debug: (message, data) => {
328
+ // Your debug logging logic
329
+ console.debug(`[Pipeline] ${message}`, data);
330
+ },
331
+ info: (message, data) => {
332
+ // Your info logging logic
333
+ console.info(`[Pipeline] ${message}`, data);
334
+ },
335
+ warn: (message, data) => {
336
+ // Your warning logging logic
337
+ console.warn(`[Pipeline] ${message}`, data);
338
+ },
339
+ error: (message, error, data) => {
340
+ // Your error logging logic
341
+ console.error(`[Pipeline] ${message}`, error, data);
342
+ },
343
+ };
344
+
345
+ <PipelineCanvasProvider logger={myLogger}>
346
+ <PipelineCanvas />
347
+ </PipelineCanvasProvider>
348
+ ```
349
+
350
+ ### Error Tracking (Sentry Example)
351
+
352
+ Integrate with error tracking services:
353
+
354
+ ```tsx
355
+ import * as Sentry from '@sentry/react';
356
+ import {
357
+ PipelineCanvasProvider,
358
+ type ErrorReporter
359
+ } from '@novoprotein/pipeline-canvas';
360
+
361
+ const errorReporter: ErrorReporter = {
362
+ captureException: (error, context) => {
363
+ Sentry.captureException(error, {
364
+ extra: context,
365
+ tags: {
366
+ component: 'pipeline-canvas',
367
+ },
368
+ });
369
+ },
370
+ captureMessage: (message, level, context) => {
371
+ Sentry.captureMessage(message, {
372
+ level: level === 'error' ? 'error' : level === 'warning' ? 'warning' : 'info',
373
+ extra: context,
374
+ tags: {
375
+ component: 'pipeline-canvas',
376
+ },
377
+ });
378
+ },
379
+ setUser: (user) => {
380
+ Sentry.setUser({
381
+ id: user.id,
382
+ email: user.email,
383
+ });
384
+ },
385
+ setContext: (key, context) => {
386
+ Sentry.setContext(key, context);
387
+ },
388
+ };
389
+
390
+ <PipelineCanvasProvider errorReporter={errorReporter}>
391
+ <PipelineCanvas />
392
+ </PipelineCanvasProvider>
393
+ ```
394
+
395
+ ### LogRocket Example
396
+
397
+ ```tsx
398
+ import LogRocket from 'logrocket';
399
+ import { PipelineCanvasProvider, type ErrorReporter } from '@novoprotein/pipeline-canvas';
400
+
401
+ const errorReporter: ErrorReporter = {
402
+ captureException: (error, context) => {
403
+ LogRocket.captureException(error, {
404
+ extra: context,
405
+ });
406
+ },
407
+ captureMessage: (message, level, context) => {
408
+ LogRocket.captureMessage(message, {
409
+ level,
410
+ extra: context,
411
+ });
412
+ },
413
+ setUser: (user) => {
414
+ LogRocket.identify(user.id, {
415
+ email: user.email,
416
+ });
417
+ },
418
+ };
419
+
420
+ <PipelineCanvasProvider errorReporter={errorReporter}>
421
+ <PipelineCanvas />
422
+ </PipelineCanvasProvider>
423
+ ```
424
+
425
+ ### Using Logger in Your Code
426
+
427
+ You can access the logger from context:
428
+
429
+ ```tsx
430
+ import { usePipelineContext } from '@novoprotein/pipeline-canvas';
431
+
432
+ function MyComponent() {
433
+ const { logger } = usePipelineContext();
434
+
435
+ const handleAction = () => {
436
+ logger?.info('Action performed', { action: 'click' });
437
+ };
438
+
439
+ return <button onClick={handleAction}>Click me</button>;
440
+ }
441
+ ```
442
+
443
+ ### What Gets Logged
444
+
445
+ The library logs:
446
+ - **Pipeline execution events**: Start, completion, errors
447
+ - **Node execution**: Status changes, errors, results
448
+ - **API requests**: Request/response details (if enabled)
449
+ - **User actions**: Pipeline save, load, delete operations
450
+ - **Errors**: All errors with full context (node ID, pipeline ID, error details)
451
+
452
+ ### Privacy and Security
453
+
454
+ - **No automatic data collection**: Logging is opt-in via dependency injection
455
+ - **You control what gets logged**: Provide your own logger/error reporter
456
+ - **No external calls**: Default logger only uses console (no network requests)
457
+ - **Context-aware**: All logs include relevant context (pipeline ID, node ID, etc.)
458
+
459
+ ### Styling
460
+
461
+ The library uses Tailwind CSS classes and shadcn/ui CSS variables. Make sure Tailwind is configured in your project:
462
+
463
+ ```js
464
+ // tailwind.config.js
465
+ module.exports = {
466
+ content: [
467
+ './src/**/*.{js,jsx,ts,tsx}',
468
+ './node_modules/@novoprotein/pipeline-canvas/**/*.{js,jsx,ts,tsx}',
469
+ ],
470
+ theme: {
471
+ extend: {
472
+ // shadcn/ui theme variables are included in the library's style.css
473
+ },
474
+ },
475
+ // ... rest of config
476
+ };
477
+ ```
478
+
479
+ Also import the CSS file in your main entry:
480
+
481
+ ```tsx
482
+ // main.tsx or App.tsx
483
+ import '@novoprotein/pipeline-canvas/style.css';
484
+ ```
485
+
486
+ The library includes shadcn/ui CSS variables for theming. The components support both light and dark themes via CSS variables.
487
+
488
+ ## Development
489
+
490
+ ```bash
491
+ # Type check
492
+ npm run type-check
493
+
494
+ # Build
495
+ npm run build
496
+ ```
497
+
498
+ ### Creating New Node Types
499
+
500
+ When creating a new node type, **please read the [Node Development Guide](../../docs/node-development-guide.md)** first. It covers critical best practices and common pitfalls, including:
501
+
502
+ - ✅ Always initialize nodes with default config
503
+ - ✅ Keep execution logs accessible after completion
504
+ - ✅ Don't force navigation during execution
505
+ - ✅ Handle multiple data structures in output extraction
506
+ - ✅ Common pitfalls and how to avoid them
507
+
508
+ This guide will save you time and prevent common issues!
509
+
510
+ ## Project Structure
511
+
512
+ ```
513
+ pipeline-canvas/
514
+ ├── components/ # React components
515
+ │ ├── PipelineCanvas.tsx
516
+ │ ├── PipelineNodeConfig.tsx
517
+ │ ├── PipelineNodePalette.tsx
518
+ │ ├── PipelineExecution.tsx
519
+ │ ├── PipelineManager.tsx
520
+ │ ├── CustomHandle.tsx
521
+ │ └── ExecutionLogsPanel.tsx
522
+ ├── nodes/ # Node type configurations (JSON)
523
+ │ ├── input_node/
524
+ │ ├── rfdiffusion_node/
525
+ │ ├── proteinmpnn_node/
526
+ │ └── alphafold_node/
527
+ ├── store/ # Zustand store
528
+ │ └── pipelineStore.ts
529
+ ├── types/ # TypeScript types
530
+ │ └── index.ts
531
+ ├── utils/ # Utility functions
532
+ │ ├── topologicalSort.ts
533
+ │ └── nodeLoader.ts
534
+ ├── dist/ # Build output (generated)
535
+ ├── index.ts # Main export file
536
+ ├── style.css # CSS styles
537
+ ├── package.json
538
+ ├── tsconfig.json
539
+ └── vite.config.ts
540
+ ```
541
+
542
+ ## License
543
+
544
+ MIT
545
+
@@ -0,0 +1,17 @@
1
+ const l = (r, n, t) => {
2
+ const e = r[n];
3
+ return e ? typeof e == "function" ? e() : Promise.resolve(e) : new Promise((i, o) => {
4
+ (typeof queueMicrotask == "function" ? queueMicrotask : setTimeout)(
5
+ o.bind(
6
+ null,
7
+ new Error(
8
+ "Unknown variable dynamic import: " + n + (n.split("/").length !== t ? ". Note that variables only represent file names one level deep." : "")
9
+ )
10
+ )
11
+ );
12
+ });
13
+ };
14
+ export {
15
+ l as default
16
+ };
17
+ //# sourceMappingURL=dynamic-import-helper.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dynamic-import-helper.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;"}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { Position } from 'reactflow';
3
+ interface CustomHandleProps {
4
+ type: 'source' | 'target';
5
+ position: Position;
6
+ }
7
+ export declare const CustomHandle: React.FC<CustomHandleProps>;
8
+ export {};
9
+ //# sourceMappingURL=CustomHandle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CustomHandle.d.ts","sourceRoot":"","sources":["../../components/CustomHandle.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAU,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE7C,UAAU,iBAAiB;IACzB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAUpD,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { jsx as s } from "react/jsx-runtime";
2
+ import { Position as r, Handle as m } from "reactflow";
3
+ const a = ({ type: e, position: t }) => {
4
+ const o = t === r.Left;
5
+ return /* @__PURE__ */ s(
6
+ m,
7
+ {
8
+ type: e,
9
+ position: t,
10
+ className: "custom-handle",
11
+ style: o ? { left: -6 } : { right: -6 }
12
+ }
13
+ );
14
+ };
15
+ export {
16
+ a as CustomHandle
17
+ };
18
+ //# sourceMappingURL=CustomHandle.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CustomHandle.mjs","sources":["../../components/CustomHandle.tsx"],"sourcesContent":["import React from 'react';\nimport { Handle, Position } from 'reactflow';\n\ninterface CustomHandleProps {\n type: 'source' | 'target';\n position: Position;\n}\n\nexport const CustomHandle: React.FC<CustomHandleProps> = ({ type, position }) => {\n const isLeft = position === Position.Left;\n return (\n <Handle\n type={type}\n position={position}\n className=\"custom-handle\"\n style={isLeft ? { left: -6 } : { right: -6 }}\n />\n );\n};\n\n\n\n\n\n"],"names":["CustomHandle","type","position","isLeft","Position","jsx","Handle"],"mappings":";;AAQO,MAAMA,IAA4C,CAAC,EAAE,MAAAC,GAAM,UAAAC,QAAe;AAC/E,QAAMC,IAASD,MAAaE,EAAS;AACrC,SACE,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,MAAAL;AAAA,MACA,UAAAC;AAAA,MACA,WAAU;AAAA,MACV,OAAOC,IAAS,EAAE,MAAM,OAAO,EAAE,OAAO,GAAA;AAAA,IAAG;AAAA,EAAA;AAGjD;"}
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export declare const ExecutionLogsPanel: React.FC;
3
+ //# sourceMappingURL=ExecutionLogsPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExecutionLogsPanel.d.ts","sourceRoot":"","sources":["../../components/ExecutionLogsPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AA8N1B,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAoItC,CAAC"}