@d34dman/flowdrop 0.0.15 → 0.0.16

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.
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Authentication Provider Types for FlowDrop
3
+ *
4
+ * Provides interfaces and implementations for authentication in FlowDrop.
5
+ * AuthProvider is passed at mount time and cannot be changed without remounting.
6
+ *
7
+ * @module types/auth
8
+ */
9
+ /**
10
+ * Static authentication provider
11
+ *
12
+ * Provides authentication using static credentials configured at instantiation.
13
+ * Suitable for simple use cases where tokens don't change during the session.
14
+ * Also used internally for backward compatibility with existing endpointConfig.auth.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * // Bearer token authentication
19
+ * const authProvider = new StaticAuthProvider({
20
+ * type: "bearer",
21
+ * token: "your-jwt-token"
22
+ * });
23
+ *
24
+ * // API key authentication
25
+ * const authProvider = new StaticAuthProvider({
26
+ * type: "api_key",
27
+ * apiKey: "your-api-key"
28
+ * });
29
+ *
30
+ * // Custom headers
31
+ * const authProvider = new StaticAuthProvider({
32
+ * type: "custom",
33
+ * headers: {
34
+ * "X-Custom-Auth": "value",
35
+ * "X-Tenant-ID": "tenant123"
36
+ * }
37
+ * });
38
+ * ```
39
+ */
40
+ export class StaticAuthProvider {
41
+ /** Cached authentication headers */
42
+ headers;
43
+ /**
44
+ * Create a new StaticAuthProvider
45
+ *
46
+ * @param config - Static authentication configuration
47
+ */
48
+ constructor(config) {
49
+ this.headers = {};
50
+ switch (config.type) {
51
+ case "bearer":
52
+ if (config.token) {
53
+ this.headers["Authorization"] = `Bearer ${config.token}`;
54
+ }
55
+ break;
56
+ case "api_key":
57
+ if (config.apiKey) {
58
+ this.headers["X-API-Key"] = config.apiKey;
59
+ }
60
+ break;
61
+ case "custom":
62
+ if (config.headers) {
63
+ this.headers = { ...config.headers };
64
+ }
65
+ break;
66
+ case "none":
67
+ default:
68
+ // No headers needed
69
+ break;
70
+ }
71
+ }
72
+ /**
73
+ * Get authentication headers
74
+ *
75
+ * Returns the statically configured headers.
76
+ *
77
+ * @returns Promise resolving to authentication headers
78
+ */
79
+ async getAuthHeaders() {
80
+ return this.headers;
81
+ }
82
+ /**
83
+ * Check if authenticated
84
+ *
85
+ * Returns true if any auth headers are configured.
86
+ *
87
+ * @returns true if headers are configured
88
+ */
89
+ isAuthenticated() {
90
+ return Object.keys(this.headers).length > 0;
91
+ }
92
+ /**
93
+ * Handle unauthorized response
94
+ *
95
+ * Static provider cannot refresh tokens, so always returns false.
96
+ *
97
+ * @returns Promise resolving to false (cannot refresh)
98
+ */
99
+ async onUnauthorized() {
100
+ // Static provider cannot refresh tokens
101
+ return false;
102
+ }
103
+ /**
104
+ * Handle forbidden response
105
+ *
106
+ * Static provider has no special handling for 403.
107
+ */
108
+ async onForbidden() {
109
+ // No special handling for static provider
110
+ }
111
+ }
112
+ /**
113
+ * Callback-based authentication provider
114
+ *
115
+ * Provides authentication using callback functions for dynamic token retrieval.
116
+ * Ideal for enterprise integrations where the parent application manages auth.
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * const authProvider = new CallbackAuthProvider({
121
+ * getToken: async () => {
122
+ * return authService.getAccessToken();
123
+ * },
124
+ * onUnauthorized: async () => {
125
+ * const refreshed = await authService.refreshToken();
126
+ * return refreshed;
127
+ * },
128
+ * onForbidden: async () => {
129
+ * showError("You don't have permission to access this resource");
130
+ * }
131
+ * });
132
+ * ```
133
+ */
134
+ export class CallbackAuthProvider {
135
+ /** Function to get the current token */
136
+ getToken;
137
+ /** Optional unauthorized callback */
138
+ onUnauthorizedCallback;
139
+ /** Optional forbidden callback */
140
+ onForbiddenCallback;
141
+ /**
142
+ * Create a new CallbackAuthProvider
143
+ *
144
+ * @param config - Callback authentication configuration
145
+ */
146
+ constructor(config) {
147
+ this.getToken = config.getToken;
148
+ this.onUnauthorizedCallback = config.onUnauthorized;
149
+ this.onForbiddenCallback = config.onForbidden;
150
+ }
151
+ /**
152
+ * Get authentication headers
153
+ *
154
+ * Calls the getToken callback to retrieve the current token.
155
+ *
156
+ * @returns Promise resolving to authentication headers
157
+ */
158
+ async getAuthHeaders() {
159
+ const token = await this.getToken();
160
+ if (token) {
161
+ return { Authorization: `Bearer ${token}` };
162
+ }
163
+ return {};
164
+ }
165
+ /**
166
+ * Check if authenticated
167
+ *
168
+ * For callback-based auth, we assume authenticated if getToken exists.
169
+ * The actual token validity is checked when making requests.
170
+ *
171
+ * @returns true (assumes authenticated, actual check happens on request)
172
+ */
173
+ isAuthenticated() {
174
+ // For callback-based auth, we assume authenticated if getToken exists
175
+ // The actual token validity is checked when making requests
176
+ return true;
177
+ }
178
+ /**
179
+ * Handle unauthorized response
180
+ *
181
+ * Calls the onUnauthorized callback if provided.
182
+ *
183
+ * @returns Promise resolving to true if auth was refreshed
184
+ */
185
+ async onUnauthorized() {
186
+ if (this.onUnauthorizedCallback) {
187
+ return this.onUnauthorizedCallback();
188
+ }
189
+ return false;
190
+ }
191
+ /**
192
+ * Handle forbidden response
193
+ *
194
+ * Calls the onForbidden callback if provided.
195
+ */
196
+ async onForbidden() {
197
+ if (this.onForbiddenCallback) {
198
+ await this.onForbiddenCallback();
199
+ }
200
+ }
201
+ }
202
+ /**
203
+ * No-op authentication provider
204
+ *
205
+ * Used when no authentication is required.
206
+ * Provides empty headers and always returns not authenticated.
207
+ */
208
+ export class NoAuthProvider {
209
+ /**
210
+ * Get authentication headers
211
+ *
212
+ * Returns empty headers (no auth).
213
+ *
214
+ * @returns Promise resolving to empty object
215
+ */
216
+ async getAuthHeaders() {
217
+ return {};
218
+ }
219
+ /**
220
+ * Check if authenticated
221
+ *
222
+ * Always returns false (no auth configured).
223
+ *
224
+ * @returns false
225
+ */
226
+ isAuthenticated() {
227
+ return false;
228
+ }
229
+ }
230
+ /**
231
+ * Create an AuthProvider from legacy endpointConfig.auth configuration
232
+ *
233
+ * Used internally for backward compatibility with existing code that uses
234
+ * the old auth configuration format in EndpointConfig.
235
+ *
236
+ * @param authConfig - Legacy auth configuration from EndpointConfig
237
+ * @returns AuthProvider instance
238
+ */
239
+ export function createAuthProviderFromLegacyConfig(authConfig) {
240
+ if (!authConfig || authConfig.type === "none") {
241
+ return new NoAuthProvider();
242
+ }
243
+ return new StaticAuthProvider(authConfig);
244
+ }
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Event Handler Types for FlowDrop
3
+ *
4
+ * Defines high-level event handlers for enterprise integration.
5
+ * These events allow parent applications to react to workflow lifecycle events.
6
+ *
7
+ * @module types/events
8
+ */
9
+ import type { Workflow } from "./index.js";
10
+ /**
11
+ * Types of workflow changes
12
+ *
13
+ * Used to identify what kind of change triggered the onWorkflowChange event.
14
+ */
15
+ export type WorkflowChangeType = "node_add" | "node_remove" | "node_move" | "node_config" | "edge_add" | "edge_remove" | "metadata" | "name" | "description";
16
+ /**
17
+ * High-level event handlers for enterprise integration
18
+ *
19
+ * These event handlers allow parent applications to hook into FlowDrop's
20
+ * workflow lifecycle. All handlers are optional.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const eventHandlers: FlowDropEventHandlers = {
25
+ * onWorkflowChange: (workflow, changeType) => {
26
+ * console.log(`Workflow changed: ${changeType}`);
27
+ * },
28
+ * onDirtyStateChange: (isDirty) => {
29
+ * updateSaveButtonState(isDirty);
30
+ * },
31
+ * onAfterSave: async (workflow) => {
32
+ * showSuccess("Workflow saved!");
33
+ * }
34
+ * };
35
+ * ```
36
+ */
37
+ export interface FlowDropEventHandlers {
38
+ /**
39
+ * Called when workflow changes (any modification)
40
+ *
41
+ * Triggered after nodes are added/removed/moved, edges are added/removed,
42
+ * or node configurations are changed.
43
+ *
44
+ * @param workflow - The updated workflow
45
+ * @param changeType - The type of change that occurred
46
+ */
47
+ onWorkflowChange?: (workflow: Workflow, changeType: WorkflowChangeType) => void;
48
+ /**
49
+ * Called when dirty state changes
50
+ *
51
+ * Triggered when the workflow transitions between saved and unsaved states.
52
+ * Useful for updating UI indicators or enabling/disabling save buttons.
53
+ *
54
+ * @param isDirty - true if there are unsaved changes
55
+ */
56
+ onDirtyStateChange?: (isDirty: boolean) => void;
57
+ /**
58
+ * Called before save - return false to cancel
59
+ *
60
+ * Allows the parent application to validate or confirm before saving.
61
+ * If this returns false, the save operation is cancelled.
62
+ *
63
+ * @param workflow - The workflow about to be saved
64
+ * @returns Promise resolving to false to cancel, true/void to proceed
65
+ */
66
+ onBeforeSave?: (workflow: Workflow) => Promise<boolean | void>;
67
+ /**
68
+ * Called after successful save
69
+ *
70
+ * Triggered after the workflow has been successfully saved to the backend.
71
+ * Useful for showing success notifications or clearing draft storage.
72
+ *
73
+ * @param workflow - The saved workflow (may include server-assigned IDs)
74
+ */
75
+ onAfterSave?: (workflow: Workflow) => Promise<void>;
76
+ /**
77
+ * Called when save fails
78
+ *
79
+ * Triggered when the save operation fails due to API error.
80
+ * Useful for showing error notifications or logging.
81
+ *
82
+ * @param error - The error that occurred
83
+ * @param workflow - The workflow that failed to save
84
+ */
85
+ onSaveError?: (error: Error, workflow: Workflow) => Promise<void>;
86
+ /**
87
+ * Called when workflow is loaded
88
+ *
89
+ * Triggered after a workflow is loaded and initialized.
90
+ * This includes both initial load and subsequent loads.
91
+ *
92
+ * @param workflow - The loaded workflow
93
+ */
94
+ onWorkflowLoad?: (workflow: Workflow) => void;
95
+ /**
96
+ * Called before unmount
97
+ *
98
+ * Triggered before FlowDrop is destroyed/unmounted.
99
+ * Allows parent application to save drafts or perform cleanup.
100
+ *
101
+ * @param workflow - The current workflow state
102
+ * @param isDirty - true if there are unsaved changes
103
+ */
104
+ onBeforeUnmount?: (workflow: Workflow, isDirty: boolean) => void;
105
+ /**
106
+ * Called on any API error
107
+ *
108
+ * Triggered when any API request fails.
109
+ * Return true to suppress FlowDrop's default error toast.
110
+ *
111
+ * @param error - The error that occurred
112
+ * @param operation - Description of the operation that failed (e.g., "save", "load", "fetchNodes")
113
+ * @returns true to suppress default error handling, false/void to show default toast
114
+ */
115
+ onApiError?: (error: Error, operation: string) => boolean | void;
116
+ }
117
+ /**
118
+ * Feature flags for FlowDrop
119
+ *
120
+ * Controls optional features and behaviors.
121
+ * All features have sensible defaults.
122
+ */
123
+ export interface FlowDropFeatures {
124
+ /**
125
+ * Save drafts to localStorage automatically
126
+ *
127
+ * When enabled, FlowDrop will periodically save the current workflow
128
+ * to localStorage as a draft. This helps prevent data loss.
129
+ *
130
+ * @default true
131
+ */
132
+ autoSaveDraft?: boolean;
133
+ /**
134
+ * Auto-save interval in milliseconds
135
+ *
136
+ * How often to save drafts to localStorage when autoSaveDraft is enabled.
137
+ *
138
+ * @default 30000 (30 seconds)
139
+ */
140
+ autoSaveDraftInterval?: number;
141
+ /**
142
+ * Show toast notifications
143
+ *
144
+ * When enabled, FlowDrop will show toast notifications for
145
+ * success, error, and loading states.
146
+ *
147
+ * @default true
148
+ */
149
+ showToasts?: boolean;
150
+ }
151
+ /**
152
+ * Default feature values
153
+ *
154
+ * Used when features are not explicitly configured.
155
+ */
156
+ export declare const DEFAULT_FEATURES: Required<FlowDropFeatures>;
157
+ /**
158
+ * Merge user-provided features with defaults
159
+ *
160
+ * @param features - User-provided feature configuration
161
+ * @returns Complete feature configuration with defaults applied
162
+ */
163
+ export declare function mergeFeatures(features?: FlowDropFeatures): Required<FlowDropFeatures>;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Event Handler Types for FlowDrop
3
+ *
4
+ * Defines high-level event handlers for enterprise integration.
5
+ * These events allow parent applications to react to workflow lifecycle events.
6
+ *
7
+ * @module types/events
8
+ */
9
+ /**
10
+ * Default feature values
11
+ *
12
+ * Used when features are not explicitly configured.
13
+ */
14
+ export const DEFAULT_FEATURES = {
15
+ autoSaveDraft: true,
16
+ autoSaveDraftInterval: 30000,
17
+ showToasts: true
18
+ };
19
+ /**
20
+ * Merge user-provided features with defaults
21
+ *
22
+ * @param features - User-provided feature configuration
23
+ * @returns Complete feature configuration with defaults applied
24
+ */
25
+ export function mergeFeatures(features) {
26
+ return {
27
+ ...DEFAULT_FEATURES,
28
+ ...features
29
+ };
30
+ }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@d34dman/flowdrop",
3
3
  "license": "MIT",
4
4
  "private": false,
5
- "version": "0.0.15",
5
+ "version": "0.0.16",
6
6
  "scripts": {
7
7
  "dev": "vite dev",
8
8
  "build": "vite build && npm run prepack",
@@ -93,7 +93,6 @@
93
93
  "@eslint/js": "^9.18.0",
94
94
  "@iconify/svelte": "^5.0.0",
95
95
  "@playwright/test": "^1.49.1",
96
- "@storybook/addon-a11y": "^9.0.15",
97
96
  "@storybook/addon-docs": "^9.0.15",
98
97
  "@storybook/addon-svelte-csf": "^5.0.4",
99
98
  "@storybook/addon-vitest": "^9.0.15",
@@ -137,4 +136,4 @@
137
136
  "svelte-5-french-toast": "^2.0.6",
138
137
  "uuid": "^11.1.0"
139
138
  }
140
- }
139
+ }