@uploadista/client-core 0.0.20-beta.6 → 0.0.20-beta.8

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/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { UploadStrategyNegotiator } from "@uploadista/core/upload";
2
2
  import { DataStoreCapabilities, InputFile, UploadEvent, UploadFile } from "@uploadista/core/types";
3
- import z from "zod";
4
3
  import { FlowData, FlowEvent, FlowJob, TypedOutput } from "@uploadista/core/flow";
4
+ import z from "zod";
5
5
  import * as _uploadista_core0 from "@uploadista/core";
6
6
  import { UploadFile as UploadFile$1 } from "@uploadista/core";
7
7
 
@@ -2769,38 +2769,185 @@ declare function createUploadistaClient<UploadInput$1>({
2769
2769
  */
2770
2770
  type UploadistaClient = ReturnType<typeof createUploadistaClient>;
2771
2771
  //#endregion
2772
- //#region src/storage/in-memory-storage-service.d.ts
2772
+ //#region src/managers/event-subscription-manager.d.ts
2773
2773
  /**
2774
- * In-memory fallback storage service for Expo
2775
- * Used when AsyncStorage is not available or for testing
2774
+ * Generic event type that the subscription manager can handle
2776
2775
  */
2777
- declare function createInMemoryStorageService(): StorageService;
2778
- //#endregion
2779
- //#region src/types/flow-result.d.ts
2780
- type FlowResult<TOutput = UploadFile> = {
2781
- type: "success";
2782
- value: TOutput;
2783
- } | {
2784
- type: "error";
2785
- error: Error;
2786
- } | {
2787
- type: "cancelled";
2788
- };
2789
- //#endregion
2790
- //#region src/types/flow-upload-item.d.ts
2776
+ interface GenericEvent {
2777
+ type: string;
2778
+ data?: unknown;
2779
+ }
2791
2780
  /**
2792
- * Flow upload item for multi-flow-upload tracking
2781
+ * Event handler callback function
2793
2782
  */
2794
- interface FlowUploadItem<UploadInput$1> {
2795
- id: string;
2796
- file: UploadInput$1;
2797
- status: "pending" | "uploading" | "success" | "error" | "aborted";
2798
- progress: number;
2799
- bytesUploaded: number;
2800
- totalBytes: number;
2801
- error: Error | null;
2802
- result: UploadFile$1 | null;
2803
- jobId: string | null;
2783
+ type SubscriptionEventHandler<T = GenericEvent> = (event: T) => void;
2784
+ /**
2785
+ * Unsubscribe function returned from subscriptions
2786
+ */
2787
+ type UnsubscribeFunction = () => void;
2788
+ /**
2789
+ * Event source that provides subscription capabilities
2790
+ */
2791
+ interface EventSource<T = GenericEvent> {
2792
+ /**
2793
+ * Subscribe to events from this source
2794
+ * @returns Unsubscribe function to clean up the subscription
2795
+ */
2796
+ subscribe(handler: SubscriptionEventHandler<T>): UnsubscribeFunction;
2797
+ }
2798
+ /**
2799
+ * Options for event filtering
2800
+ */
2801
+ interface EventFilterOptions {
2802
+ /**
2803
+ * Filter events by type (exact match)
2804
+ */
2805
+ eventType?: string;
2806
+ /**
2807
+ * Filter events by upload/job ID
2808
+ * If provided, only events with matching ID will be passed to the handler
2809
+ */
2810
+ uploadId?: string | null;
2811
+ /**
2812
+ * Custom filter function for advanced filtering
2813
+ * Return true to pass the event to the handler
2814
+ */
2815
+ customFilter?: (event: GenericEvent) => boolean;
2816
+ }
2817
+ /**
2818
+ * Platform-agnostic event subscription manager that handles event filtering,
2819
+ * subscription tracking, and automatic cleanup.
2820
+ *
2821
+ * This manager simplifies event handling by:
2822
+ * - Filtering events by type and/or ID
2823
+ * - Tracking all active subscriptions
2824
+ * - Providing cleanup methods to unsubscribe from all events
2825
+ * - Supporting custom filter functions for advanced scenarios
2826
+ *
2827
+ * @example Basic event subscription
2828
+ * ```typescript
2829
+ * const manager = new EventSubscriptionManager(eventSource);
2830
+ *
2831
+ * manager.subscribe(
2832
+ * (event) => console.log('Upload progress:', event),
2833
+ * { eventType: 'UPLOAD_PROGRESS', uploadId: 'abc123' }
2834
+ * );
2835
+ *
2836
+ * // Clean up all subscriptions when done
2837
+ * manager.cleanup();
2838
+ * ```
2839
+ *
2840
+ * @example Multiple filtered subscriptions
2841
+ * ```typescript
2842
+ * const manager = new EventSubscriptionManager(eventSource);
2843
+ *
2844
+ * // Subscribe to progress events for specific upload
2845
+ * manager.subscribe(
2846
+ * onProgress,
2847
+ * { eventType: 'UPLOAD_PROGRESS', uploadId: currentUploadId }
2848
+ * );
2849
+ *
2850
+ * // Subscribe to error events for any upload
2851
+ * manager.subscribe(
2852
+ * onError,
2853
+ * { eventType: 'UPLOAD_ERROR' }
2854
+ * );
2855
+ *
2856
+ * // Subscribe to all events with custom filtering
2857
+ * manager.subscribe(
2858
+ * onEvent,
2859
+ * { customFilter: (e) => e.data?.priority === 'high' }
2860
+ * );
2861
+ * ```
2862
+ */
2863
+ declare class EventSubscriptionManager<T extends GenericEvent = GenericEvent> {
2864
+ private readonly eventSource;
2865
+ private subscriptions;
2866
+ /**
2867
+ * Create a new EventSubscriptionManager
2868
+ *
2869
+ * @param eventSource - Source to subscribe to for events
2870
+ */
2871
+ constructor(eventSource: EventSource<T>);
2872
+ /**
2873
+ * Subscribe to events with optional filtering
2874
+ *
2875
+ * @param handler - Callback function to invoke when matching events occur
2876
+ * @param filter - Optional filter options to narrow down which events trigger the handler
2877
+ * @returns Unsubscribe function to remove this specific subscription
2878
+ *
2879
+ * @example Subscribe to specific event type
2880
+ * ```typescript
2881
+ * const unsubscribe = manager.subscribe(
2882
+ * (event) => console.log('Progress:', event),
2883
+ * { eventType: 'UPLOAD_PROGRESS' }
2884
+ * );
2885
+ *
2886
+ * // Later, unsubscribe
2887
+ * unsubscribe();
2888
+ * ```
2889
+ */
2890
+ subscribe(handler: SubscriptionEventHandler<T>, filter?: EventFilterOptions): UnsubscribeFunction;
2891
+ /**
2892
+ * Check if an event matches the filter criteria
2893
+ *
2894
+ * @param event - Event to check
2895
+ * @param filter - Filter options to apply
2896
+ * @returns True if the event passes all filters
2897
+ */
2898
+ private shouldHandleEvent;
2899
+ /**
2900
+ * Get the number of active subscriptions
2901
+ *
2902
+ * @returns Number of tracked subscriptions
2903
+ */
2904
+ getSubscriptionCount(): number;
2905
+ /**
2906
+ * Check if there are any active subscriptions
2907
+ *
2908
+ * @returns True if at least one subscription is active
2909
+ */
2910
+ hasSubscriptions(): boolean;
2911
+ /**
2912
+ * Unsubscribe from all tracked subscriptions and clear the subscription list
2913
+ *
2914
+ * This is typically called when disposing of a component or cleaning up resources.
2915
+ *
2916
+ * @example Cleanup in framework hooks
2917
+ * ```typescript
2918
+ * // React
2919
+ * useEffect(() => {
2920
+ * const manager = new EventSubscriptionManager(eventSource);
2921
+ * manager.subscribe(handler, filter);
2922
+ *
2923
+ * return () => manager.cleanup();
2924
+ * }, []);
2925
+ *
2926
+ * // Vue
2927
+ * onUnmounted(() => {
2928
+ * manager.cleanup();
2929
+ * });
2930
+ * ```
2931
+ */
2932
+ cleanup(): void;
2933
+ /**
2934
+ * Update the upload ID filter for all subscriptions that have an uploadId filter
2935
+ *
2936
+ * This is useful when the current upload changes and you want to update
2937
+ * all subscriptions to listen for the new upload's events.
2938
+ *
2939
+ * @param newUploadId - New upload ID to filter events by
2940
+ *
2941
+ * @example Update upload ID when starting new upload
2942
+ * ```typescript
2943
+ * const manager = new EventSubscriptionManager(eventSource);
2944
+ * manager.subscribe(onProgress, { eventType: 'UPLOAD_PROGRESS', uploadId: null });
2945
+ *
2946
+ * // When upload starts
2947
+ * manager.updateUploadIdFilter(uploadId);
2948
+ * ```
2949
+ */
2950
+ updateUploadIdFilter(newUploadId: string | null): void;
2804
2951
  }
2805
2952
  //#endregion
2806
2953
  //#region src/types/flow-upload-options.d.ts
@@ -2877,643 +3024,472 @@ interface FlowUploadOptions {
2877
3024
  onShouldRetry?: (error: Error, retryAttempt: number) => boolean;
2878
3025
  }
2879
3026
  //#endregion
2880
- //#region src/types/flow-inputs.d.ts
3027
+ //#region src/managers/flow-manager.d.ts
2881
3028
  /**
2882
- * Type definitions for flexible flow input specifications.
2883
- *
2884
- * This module defines types for passing input data to flows with multiple input nodes.
2885
- * The FlowInputs type maps node IDs to their respective input data, enabling support
2886
- * for flows with single or multiple input points.
2887
- *
2888
- * @module types/flow-inputs
2889
- *
2890
- * @example
2891
- * ```typescript
2892
- * import type { FlowInputs } from "@uploadista/client-core";
2893
- *
2894
- * // Single input flow
2895
- * const inputs: FlowInputs = {
2896
- * "file-input": {
2897
- * operation: "url",
2898
- * url: "https://example.com/image.jpg"
2899
- * }
2900
- * };
2901
- *
2902
- * // Multi-input flow
2903
- * const multiInputs: FlowInputs = {
2904
- * "file-input": {
2905
- * operation: "init",
2906
- * storageId: "s3",
2907
- * metadata: { originalName: "image.jpg" }
2908
- * },
2909
- * "metadata-input": {
2910
- * title: "My Image",
2911
- * tags: ["photo", "landscape"]
2912
- * }
2913
- * };
2914
- * ```
3029
+ * Flow upload status representing the current state of a flow upload lifecycle.
3030
+ * Flow uploads progress through: idle → uploading → processing → success/error/aborted
2915
3031
  */
3032
+ type FlowUploadStatus = "idle" | "uploading" | "processing" | "success" | "error" | "aborted";
2916
3033
  /**
2917
- * Flow input specification mapping node IDs to their input data.
2918
- *
2919
- * This type represents a map of input node IDs to their respective input data.
2920
- * Each key is a node ID, and each value is the data to pass to that node.
2921
- * The data structure depends on the node's registered input type.
2922
- *
2923
- * @remarks
2924
- * Input data is validated against each node's registered type schema before
2925
- * flow execution begins. Invalid data will result in validation errors.
2926
- *
2927
- * @example
2928
- * ```typescript
2929
- * // For streaming input node (init operation)
2930
- * const fileUploadInputs: FlowInputs = {
2931
- * "input-node-1": {
2932
- * operation: "init",
2933
- * storageId: "my-storage",
2934
- * metadata: {
2935
- * originalName: "photo.jpg",
2936
- * mimeType: "image/jpeg",
2937
- * size: 1024000
2938
- * }
2939
- * }
2940
- * };
2941
- *
2942
- * // For streaming input node (URL operation)
2943
- * const urlInputs: FlowInputs = {
2944
- * "input-node-1": {
2945
- * operation: "url",
2946
- * url: "https://example.com/photo.jpg",
2947
- * storageId: "my-storage",
2948
- * metadata: {
2949
- * source: "external"
2950
- * }
2951
- * }
2952
- * };
2953
- * ```
2954
- */
2955
- type FlowInputs = Record<string, unknown>;
2956
- /**
2957
- * Helper type for single-input flows.
2958
- *
2959
- * Many flows have exactly one input node. This helper type makes it easier
2960
- * to work with single-input scenarios without needing to know the node ID upfront.
2961
- *
2962
- * @example
2963
- * ```typescript
2964
- * const singleInput: SingleFlowInput = {
2965
- * operation: "url",
2966
- * url: "https://example.com/image.jpg"
2967
- * };
2968
- *
2969
- * // The client can auto-discover the input node ID and convert this to FlowInputs
2970
- * ```
2971
- */
2972
- type SingleFlowInput = unknown;
2973
- /**
2974
- * Result of input node discovery.
2975
- *
2976
- * Contains information about discovered input nodes in a flow, including
2977
- * their IDs, types, and whether the flow has a single or multiple inputs.
2978
- *
2979
- * @property inputNodes - Array of input node information
2980
- * @property single - True if flow has exactly one input node
3034
+ * Complete state information for a flow upload operation.
3035
+ * Tracks both the upload phase (file transfer) and processing phase (flow execution).
2981
3036
  */
2982
- interface InputNodeDiscovery {
2983
- inputNodes: Array<{
2984
- id: string;
2985
- type: string;
2986
- name?: string;
2987
- }>;
2988
- single: boolean;
2989
- }
2990
- //#endregion
2991
- //#region src/types/multi-flow-upload-options.d.ts
2992
- interface MultiFlowUploadOptions<UploadInput$1> {
2993
- /**
2994
- * Flow configuration
2995
- */
2996
- flowConfig: FlowUploadConfig;
2997
- /**
2998
- * Maximum number of concurrent uploads (default: 3)
2999
- */
3000
- maxConcurrent?: number;
3001
- /**
3002
- * Called when an individual upload progresses
3003
- */
3004
- onItemProgress?: (item: FlowUploadItem<UploadInput$1>) => void;
3005
- /**
3006
- * Called when an individual upload succeeds
3007
- */
3008
- onItemSuccess?: (item: FlowUploadItem<UploadInput$1>) => void;
3009
- /**
3010
- * Called when an individual upload fails
3011
- */
3012
- onItemError?: (item: FlowUploadItem<UploadInput$1>, error: Error) => void;
3013
- /**
3014
- * Called when all uploads complete
3015
- */
3016
- onComplete?: (items: FlowUploadItem<UploadInput$1>[]) => void;
3037
+ interface FlowUploadState {
3038
+ /** Current upload status */
3039
+ status: FlowUploadStatus;
3040
+ /** Upload progress percentage (0-100) */
3041
+ progress: number;
3042
+ /** Number of bytes uploaded */
3043
+ bytesUploaded: number;
3044
+ /** Total bytes to upload, null if unknown */
3045
+ totalBytes: number | null;
3046
+ /** Error if upload or processing failed */
3047
+ error: Error | null;
3048
+ /** Unique identifier for the flow execution job */
3049
+ jobId: string | null;
3050
+ /** Whether the flow processing has started */
3051
+ flowStarted: boolean;
3052
+ /** Name of the currently executing flow node */
3053
+ currentNodeName: string | null;
3054
+ /** Type of the currently executing flow node */
3055
+ currentNodeType: string | null;
3017
3056
  /**
3018
- * Custom retry logic
3057
+ * Complete typed outputs from all output nodes in the flow.
3058
+ * Each output includes nodeId, optional nodeType, data, and timestamp.
3059
+ * Available when status is "success".
3019
3060
  */
3020
- onShouldRetry?: (error: Error, retryAttempt: number) => boolean;
3061
+ flowOutputs: TypedOutput[] | null;
3021
3062
  }
3022
- //#endregion
3023
- //#region src/types/multi-flow-upload-state.d.ts
3024
- interface MultiFlowUploadState<UploadInput$1> {
3025
- items: FlowUploadItem<UploadInput$1>[];
3026
- totalProgress: number;
3027
- activeUploads: number;
3028
- completedUploads: number;
3029
- failedUploads: number;
3063
+ /**
3064
+ * State for a single input in a multi-input flow.
3065
+ */
3066
+ interface InputExecutionState {
3067
+ /** Input node ID */
3068
+ nodeId: string;
3069
+ /** Input type (file, url, data) */
3070
+ type: "file" | "url" | "data";
3071
+ /** Current status of this input */
3072
+ status: "pending" | "uploading" | "complete" | "error";
3073
+ /** Progress percentage for file uploads (0-100) */
3074
+ progress: number;
3075
+ /** Bytes uploaded for file uploads */
3076
+ bytesUploaded: number;
3077
+ /** Total bytes for file uploads */
3078
+ totalBytes: number | null;
3079
+ /** Error if this input failed */
3080
+ error: Error | null;
3081
+ /** Abort controller for this specific input */
3082
+ abortController: FlowUploadAbortController | null;
3030
3083
  }
3031
- //#endregion
3032
- //#region src/types/upload-options.d.ts
3033
- interface UploadOptions {
3034
- /**
3035
- * Upload metadata to attach to the file
3036
- */
3037
- metadata?: Record<string, string>;
3038
- /**
3039
- * Whether to defer the upload size calculation
3040
- */
3041
- uploadLengthDeferred?: boolean;
3084
+ /**
3085
+ * Callbacks that FlowManager invokes during the flow upload lifecycle
3086
+ */
3087
+ interface FlowManagerCallbacks {
3042
3088
  /**
3043
- * Manual upload size override
3089
+ * Called when the flow upload state changes
3044
3090
  */
3045
- uploadSize?: number;
3091
+ onStateChange: (state: FlowUploadState) => void;
3046
3092
  /**
3047
3093
  * Called when upload progress updates
3048
- *
3049
- * @param uploadId - The unique identifier for this upload
3050
- * @param bytesUploaded - Number of bytes uploaded so far
3051
- * @param totalBytes - Total bytes to upload, null if unknown/deferred
3094
+ * @param progress - Progress percentage (0-100)
3095
+ * @param bytesUploaded - Number of bytes uploaded
3096
+ * @param totalBytes - Total bytes to upload, null if unknown
3052
3097
  */
3053
3098
  onProgress?: (uploadId: string, bytesUploaded: number, totalBytes: number | null) => void;
3054
3099
  /**
3055
3100
  * Called when a chunk completes
3056
- *
3057
- * @param chunkSize - Size of the completed chunk in bytes
3058
- * @param bytesAccepted - Total bytes accepted by server so far
3059
- * @param bytesTotal - Total bytes to upload, null if unknown/deferred
3101
+ * @param chunkSize - Size of the completed chunk
3102
+ * @param bytesAccepted - Total bytes accepted so far
3103
+ * @param bytesTotal - Total bytes to upload, null if unknown
3060
3104
  */
3061
3105
  onChunkComplete?: (chunkSize: number, bytesAccepted: number, bytesTotal: number | null) => void;
3062
3106
  /**
3063
- * Called when upload succeeds
3107
+ * Called when the flow completes successfully (receives full flow outputs)
3108
+ * Each output includes nodeId, optional nodeType (e.g., "storage-output-v1"), data, and timestamp.
3064
3109
  *
3065
- * @param result - The uploaded file result
3110
+ * @param outputs - Array of typed outputs from all output nodes
3111
+ *
3112
+ * @example
3113
+ * ```typescript
3114
+ * onFlowComplete: (outputs) => {
3115
+ * for (const output of outputs) {
3116
+ * console.log(`${output.nodeId} (${output.nodeType}):`, output.data);
3117
+ * }
3118
+ * }
3119
+ * ```
3066
3120
  */
3067
- onSuccess?: (result: UploadFile$1) => void;
3121
+ onFlowComplete?: (outputs: TypedOutput[]) => void;
3068
3122
  /**
3069
- * Called when upload fails
3123
+ * Called when upload succeeds (receives typed outputs from all output nodes)
3124
+ * Each output includes nodeId, optional nodeType (e.g., "storage-output-v1"), data, and timestamp.
3070
3125
  *
3071
- * @param error - The error that caused the failure
3126
+ * @param outputs - Array of typed outputs from all output nodes
3127
+ *
3128
+ * @example
3129
+ * ```typescript
3130
+ * onSuccess: (outputs) => {
3131
+ * for (const output of outputs) {
3132
+ * console.log(`${output.nodeId} completed:`, output.data);
3133
+ * }
3134
+ * }
3135
+ * ```
3072
3136
  */
3073
- onError?: (error: Error) => void;
3137
+ onSuccess?: (outputs: TypedOutput[]) => void;
3074
3138
  /**
3075
- * Called when upload is aborted
3139
+ * Called when upload or flow processing fails with an error
3140
+ * @param error - The error that occurred
3076
3141
  */
3077
- onAbort?: () => void;
3142
+ onError?: (error: Error) => void;
3078
3143
  /**
3079
- * Custom retry logic
3080
- *
3081
- * @param error - The error that triggered the retry check
3082
- * @param retryAttempt - The current retry attempt number (0-indexed)
3083
- * @returns true to retry, false to fail
3144
+ * Called when upload or flow is aborted
3084
3145
  */
3085
- onShouldRetry?: (error: Error, retryAttempt: number) => boolean;
3146
+ onAbort?: () => void;
3086
3147
  }
3087
- //#endregion
3088
- //#region src/types/upload-metrics.d.ts
3089
3148
  /**
3090
- * Comprehensive upload metrics interface
3091
- *
3092
- * Provides access to all performance metrics, insights, and network
3093
- * statistics for upload monitoring and optimization.
3094
- *
3095
- * This interface is implemented by all framework packages (React, Vue, React Native)
3096
- * to ensure consistent metrics API across platforms.
3097
- *
3098
- * @example React usage
3099
- * ```tsx
3100
- * const upload = useUpload();
3101
- * const insights = upload.metrics.getInsights();
3102
- * const metrics = upload.metrics.exportMetrics();
3103
- * ```
3104
- *
3105
- * @example Vue usage
3106
- * ```vue
3107
- * <script setup>
3108
- * const upload = useUpload();
3109
- * const insights = upload.metrics.getInsights();
3110
- * </script>
3111
- * ```
3149
+ * Generic flow execution input type - can be any value that the flow execution client accepts.
3150
+ * Common types include File, Blob, string (for URLs), or structured data objects.
3112
3151
  *
3113
- * @example React Native usage
3114
- * ```tsx
3115
- * const upload = useUpload();
3116
- * const networkMetrics = upload.metrics.getNetworkMetrics();
3117
- * ```
3152
+ * @remarks
3153
+ * The flexibility of this type enables different flow execution patterns:
3154
+ * - File/Blob: Traditional chunked file upload with init/finalize operations
3155
+ * - string (URL): Direct file fetch from external URL
3156
+ * - object: Structured data for non-file input nodes (future)
3118
3157
  */
3119
- interface UploadMetrics {
3120
- /**
3121
- * Get performance insights from the upload client
3122
- *
3123
- * Provides high-level analysis with recommendations for
3124
- * optimizing upload performance.
3125
- *
3126
- * @returns Performance insights including efficiency scores and recommendations
3127
- *
3128
- * @example
3129
- * ```typescript
3130
- * const insights = metrics.getInsights();
3131
- * console.log(`Efficiency: ${insights.overallEfficiency}%`);
3132
- * console.log(`Recommendations:`, insights.recommendations);
3133
- * ```
3134
- */
3135
- getInsights: () => PerformanceInsights;
3136
- /**
3137
- * Export detailed metrics from the upload client
3138
- *
3139
- * Returns comprehensive metrics including session data,
3140
- * per-chunk statistics, and performance insights.
3141
- *
3142
- * Useful for analytics, debugging, and performance monitoring.
3143
- *
3144
- * @returns Object containing session metrics, chunk metrics, and insights
3145
- *
3146
- * @example
3147
- * ```typescript
3148
- * const metrics = metrics.exportMetrics();
3149
- * console.log(`Uploaded ${metrics.session.totalBytesUploaded} bytes`);
3150
- * console.log(`Average speed: ${metrics.session.averageSpeed} B/s`);
3151
- * console.log(`Chunks: ${metrics.chunks.length}`);
3152
- * ```
3153
- */
3154
- exportMetrics: () => {
3155
- /** Session-level aggregated metrics */
3156
- session: Partial<UploadSessionMetrics>;
3157
- /** Per-chunk detailed metrics */
3158
- chunks: ChunkMetrics[];
3159
- /** Performance insights and recommendations */
3160
- insights: PerformanceInsights;
3161
- };
3158
+ type FlowUploadInput = unknown;
3159
+ /**
3160
+ * Flow configuration for upload
3161
+ */
3162
+ interface FlowConfig {
3163
+ flowId: string;
3164
+ storageId: string;
3165
+ outputNodeId?: string;
3166
+ metadata?: Record<string, string>;
3167
+ }
3168
+ /**
3169
+ * Abort and pause controller interface for canceling/pausing flow uploads
3170
+ */
3171
+ interface FlowUploadAbortController {
3172
+ abort: () => void | Promise<void>;
3173
+ pause: () => void | Promise<void>;
3174
+ }
3175
+ /**
3176
+ * Internal upload options used by the flow upload function.
3177
+ * The upload phase always returns UploadFile, regardless of the final TOutput type.
3178
+ */
3179
+ interface InternalFlowUploadOptions {
3180
+ onJobStart?: (jobId: string) => void;
3181
+ onProgress?: (uploadId: string, bytesUploaded: number, totalBytes: number | null) => void;
3182
+ onChunkComplete?: (chunkSize: number, bytesAccepted: number, bytesTotal: number | null) => void;
3183
+ onSuccess?: (result: UploadFile) => void;
3184
+ onError?: (error: Error) => void;
3185
+ onAbort?: () => void;
3186
+ onShouldRetry?: (error: Error, retryAttempt: number) => boolean;
3187
+ }
3188
+ /**
3189
+ * Flow upload function that performs the actual upload with flow processing.
3190
+ * Returns a promise that resolves to an abort controller with pause capability.
3191
+ *
3192
+ * Note: The upload phase onSuccess always receives UploadFile. The final TOutput
3193
+ * result comes from the flow execution and is handled via FlowEnd events.
3194
+ */
3195
+ type FlowUploadFunction<TInput = FlowUploadInput> = (input: TInput, flowConfig: FlowConfig, options: InternalFlowUploadOptions) => Promise<FlowUploadAbortController>;
3196
+ /**
3197
+ * Callbacks for tracking individual input progress in multi-input flows
3198
+ */
3199
+ interface MultiInputCallbacks {
3162
3200
  /**
3163
- * Get current network metrics
3164
- *
3165
- * Provides real-time network statistics including speed,
3166
- * errors, and network condition assessment.
3167
- *
3168
- * @returns Current network performance metrics
3169
- *
3170
- * @example
3171
- * ```typescript
3172
- * const network = metrics.getNetworkMetrics();
3173
- * console.log(`Speed: ${network.currentSpeed} B/s`);
3174
- * console.log(`Quality: ${network.condition.quality}`);
3175
- * ```
3201
+ * Called when an input's progress updates
3202
+ * @param nodeId - The input node ID
3203
+ * @param progress - Progress percentage (0-100)
3204
+ * @param bytesUploaded - Bytes uploaded for this input
3205
+ * @param totalBytes - Total bytes for this input
3176
3206
  */
3177
- getNetworkMetrics: () => NetworkMetrics;
3207
+ onInputProgress?: (nodeId: string, progress: number, bytesUploaded: number, totalBytes: number | null) => void;
3178
3208
  /**
3179
- * Get current network condition
3180
- *
3181
- * Provides assessment of current network quality with
3182
- * recommendations for adaptive upload strategies.
3183
- *
3184
- * @returns Network condition assessment
3185
- *
3186
- * @example
3187
- * ```typescript
3188
- * const condition = metrics.getNetworkCondition();
3189
- * if (condition.quality === 'poor') {
3190
- * console.log('Consider reducing chunk size');
3191
- * }
3192
- * ```
3209
+ * Called when an input completes successfully
3210
+ * @param nodeId - The input node ID
3193
3211
  */
3194
- getNetworkCondition: () => NetworkCondition;
3212
+ onInputComplete?: (nodeId: string) => void;
3195
3213
  /**
3196
- * Reset all metrics
3197
- *
3198
- * Clears all accumulated metrics and resets counters.
3199
- * Useful when starting a new upload session.
3200
- *
3201
- * @example
3202
- * ```typescript
3203
- * // Reset metrics before starting new upload
3204
- * metrics.resetMetrics();
3205
- * upload(newFile);
3206
- * ```
3214
+ * Called when an input fails
3215
+ * @param nodeId - The input node ID
3216
+ * @param error - The error that occurred
3207
3217
  */
3208
- resetMetrics: () => void;
3218
+ onInputError?: (nodeId: string, error: Error) => void;
3209
3219
  }
3210
- //#endregion
3211
- //#region src/types/upload-result.d.ts
3212
3220
  /**
3213
- * Discriminated union representing the result of an upload operation.
3214
- *
3215
- * Provides a type-safe way to handle the three possible outcomes of an upload:
3216
- * success, error, or cancellation. This pattern enables exhaustive checking
3217
- * of all cases at compile time.
3221
+ * Multi-input flow upload function that coordinates multiple inputs in a single flow.
3222
+ * Platform packages should implement this to enable parallel multi-input upload support.
3218
3223
  *
3219
- * @template TOutput - The type of the successful result value. Defaults to UploadFile
3224
+ * @param inputs - Record of nodeId to input data (File, URL string, or structured data)
3225
+ * @param flowConfig - Flow configuration
3226
+ * @param options - Upload callbacks and configuration
3227
+ * @param multiInputCallbacks - Per-input progress tracking callbacks
3228
+ * @returns Promise resolving to abort controller for the entire flow execution
3220
3229
  *
3221
- * @example Handling upload results
3230
+ * @example
3222
3231
  * ```typescript
3223
- * function handleUploadResult(result: UploadResult) {
3224
- * switch (result.type) {
3225
- * case 'success':
3226
- * console.log('Upload complete:', result.value.id);
3227
- * break;
3228
- * case 'error':
3229
- * console.error('Upload failed:', result.error.message);
3230
- * break;
3231
- * case 'cancelled':
3232
- * console.log('Upload was cancelled by user');
3233
- * break;
3234
- * }
3235
- * }
3232
+ * const uploadFn: MultiInputFlowUploadFunction = async (inputs, flowConfig, options, callbacks) => {
3233
+ * // 1. Start flow and create job
3234
+ * const jobId = await startFlow(flowConfig.flowId, flowConfig.storageId);
3235
+ *
3236
+ * // 2. Initialize all inputs in parallel using orchestrator functions
3237
+ * const initPromises = Object.entries(inputs).map(([nodeId, data]) =>
3238
+ * initializeFlowInput({ nodeId, jobId, source: data, ... })
3239
+ * );
3240
+ *
3241
+ * // 3. Upload files in parallel
3242
+ * // 4. Finalize all inputs
3243
+ * // 5. Return abort controller
3244
+ * };
3236
3245
  * ```
3246
+ */
3247
+ type MultiInputFlowUploadFunction = (inputs: Record<string, unknown>, flowConfig: FlowConfig, options: InternalFlowUploadOptions, multiInputCallbacks?: MultiInputCallbacks) => Promise<FlowUploadAbortController>;
3248
+ /**
3249
+ * Platform-agnostic flow execution manager that handles flow state machine,
3250
+ * progress tracking, flow event handling, error handling, abort, pause, reset, and retry logic.
3237
3251
  *
3238
- * @example With custom output type
3252
+ * Supports multiple input types through generic TInput parameter:
3253
+ * - File/Blob: Chunked file upload with progress tracking
3254
+ * - string (URL): Direct file fetch from external source
3255
+ * - object: Structured data for custom input nodes
3256
+ *
3257
+ * Framework packages (React, Vue, React Native) should wrap this manager
3258
+ * with framework-specific hooks/composables.
3259
+ *
3260
+ * @template TInput - The type of input data accepted by the flow (File, Blob, string, object, etc.)
3261
+ *
3262
+ * @example
3239
3263
  * ```typescript
3240
- * interface ProcessedImage {
3241
- * url: string;
3242
- * width: number;
3243
- * height: number;
3244
- * }
3264
+ * // File upload flow
3265
+ * const fileFlowManager = new FlowManager<File>(...);
3266
+ * await fileFlowManager.upload(myFile);
3245
3267
  *
3246
- * const result: UploadResult<ProcessedImage> = await uploadAndProcess(file);
3268
+ * // URL fetch flow
3269
+ * const urlFlowManager = new FlowManager<string>(...);
3270
+ * await urlFlowManager.upload("https://example.com/image.jpg");
3247
3271
  *
3248
- * if (result.type === 'success') {
3249
- * console.log(`Image processed: ${result.value.width}x${result.value.height}`);
3250
- * }
3272
+ * // Structured data flow
3273
+ * const dataFlowManager = new FlowManager<{ text: string }>(...);
3274
+ * await dataFlowManager.upload({ text: "Process this" });
3251
3275
  * ```
3252
3276
  */
3253
- type UploadResult<TOutput = UploadFile$1> = {
3254
- /** Indicates the upload completed successfully */
3255
- type: "success";
3256
- /** The successful result value (e.g., upload metadata or processed output) */
3257
- value: TOutput;
3258
- } | {
3259
- /** Indicates the upload failed with an error */
3260
- type: "error";
3261
- /** The error that caused the upload to fail */
3262
- error: Error;
3263
- } | {
3264
- /** Indicates the upload was cancelled by the user or application */
3265
- type: "cancelled";
3266
- };
3267
- //#endregion
3268
- //#region src/managers/event-subscription-manager.d.ts
3269
- /**
3270
- * Generic event type that the subscription manager can handle
3271
- */
3272
- interface GenericEvent {
3273
- type: string;
3274
- data?: unknown;
3275
- }
3276
- /**
3277
- * Event handler callback function
3278
- */
3279
- type SubscriptionEventHandler<T = GenericEvent> = (event: T) => void;
3280
- /**
3281
- * Unsubscribe function returned from subscriptions
3282
- */
3283
- type UnsubscribeFunction = () => void;
3284
- /**
3285
- * Event source that provides subscription capabilities
3286
- */
3287
- interface EventSource<T = GenericEvent> {
3277
+ declare class FlowManager<TInput = FlowUploadInput> {
3278
+ private readonly flowUploadFn;
3279
+ private readonly callbacks;
3280
+ private readonly options;
3281
+ private readonly multiInputUploadFn?;
3282
+ private state;
3283
+ private abortController;
3284
+ private inputStates;
3285
+ /** Tracks the nodeId when executing a single-input flow via executeFlow() */
3286
+ private currentSingleInputNodeId;
3287
+ /**
3288
+ * Create a new FlowManager
3289
+ *
3290
+ * @param flowUploadFn - Flow upload function to use for uploads
3291
+ * @param callbacks - Callbacks to invoke during flow upload lifecycle
3292
+ * @param options - Flow upload configuration options
3293
+ * @param multiInputUploadFn - Optional multi-input upload function for executeFlow()
3294
+ */
3295
+ constructor(flowUploadFn: FlowUploadFunction<TInput>, callbacks: FlowManagerCallbacks, options: FlowUploadOptions, multiInputUploadFn?: MultiInputFlowUploadFunction | undefined);
3296
+ /**
3297
+ * Get the current flow upload state
3298
+ */
3299
+ getState(): FlowUploadState;
3300
+ /**
3301
+ * Check if an upload or flow is currently active
3302
+ */
3303
+ isUploading(): boolean;
3304
+ /**
3305
+ * Check if file upload is in progress
3306
+ */
3307
+ isUploadingFile(): boolean;
3288
3308
  /**
3289
- * Subscribe to events from this source
3290
- * @returns Unsubscribe function to clean up the subscription
3309
+ * Check if flow processing is in progress
3291
3310
  */
3292
- subscribe(handler: SubscriptionEventHandler<T>): UnsubscribeFunction;
3293
- }
3294
- /**
3295
- * Options for event filtering
3296
- */
3297
- interface EventFilterOptions {
3311
+ isProcessing(): boolean;
3298
3312
  /**
3299
- * Filter events by type (exact match)
3313
+ * Get the current job ID
3300
3314
  */
3301
- eventType?: string;
3315
+ getJobId(): string | null;
3302
3316
  /**
3303
- * Filter events by upload/job ID
3304
- * If provided, only events with matching ID will be passed to the handler
3317
+ * Update the internal state and notify callbacks
3305
3318
  */
3306
- uploadId?: string | null;
3319
+ private updateState;
3307
3320
  /**
3308
- * Custom filter function for advanced filtering
3309
- * Return true to pass the event to the handler
3321
+ * Handle flow events from the event subscription
3322
+ * This method should be called by the framework wrapper when it receives flow events
3323
+ *
3324
+ * @param event - Flow event to process
3310
3325
  */
3311
- customFilter?: (event: GenericEvent) => boolean;
3312
- }
3313
- /**
3314
- * Platform-agnostic event subscription manager that handles event filtering,
3315
- * subscription tracking, and automatic cleanup.
3316
- *
3317
- * This manager simplifies event handling by:
3318
- * - Filtering events by type and/or ID
3319
- * - Tracking all active subscriptions
3320
- * - Providing cleanup methods to unsubscribe from all events
3321
- * - Supporting custom filter functions for advanced scenarios
3322
- *
3323
- * @example Basic event subscription
3324
- * ```typescript
3325
- * const manager = new EventSubscriptionManager(eventSource);
3326
- *
3327
- * manager.subscribe(
3328
- * (event) => console.log('Upload progress:', event),
3329
- * { eventType: 'UPLOAD_PROGRESS', uploadId: 'abc123' }
3330
- * );
3331
- *
3332
- * // Clean up all subscriptions when done
3333
- * manager.cleanup();
3334
- * ```
3335
- *
3336
- * @example Multiple filtered subscriptions
3337
- * ```typescript
3338
- * const manager = new EventSubscriptionManager(eventSource);
3339
- *
3340
- * // Subscribe to progress events for specific upload
3341
- * manager.subscribe(
3342
- * onProgress,
3343
- * { eventType: 'UPLOAD_PROGRESS', uploadId: currentUploadId }
3344
- * );
3345
- *
3346
- * // Subscribe to error events for any upload
3347
- * manager.subscribe(
3348
- * onError,
3349
- * { eventType: 'UPLOAD_ERROR' }
3350
- * );
3351
- *
3352
- * // Subscribe to all events with custom filtering
3353
- * manager.subscribe(
3354
- * onEvent,
3355
- * { customFilter: (e) => e.data?.priority === 'high' }
3356
- * );
3357
- * ```
3358
- */
3359
- declare class EventSubscriptionManager<T extends GenericEvent = GenericEvent> {
3360
- private readonly eventSource;
3361
- private subscriptions;
3326
+ handleFlowEvent(event: FlowEvent): void;
3362
3327
  /**
3363
- * Create a new EventSubscriptionManager
3328
+ * Handle upload progress events from the event subscription
3329
+ * This method should be called by the framework wrapper when it receives upload progress events
3364
3330
  *
3365
- * @param eventSource - Source to subscribe to for events
3331
+ * @param uploadId - The unique identifier for this upload
3332
+ * @param bytesUploaded - Number of bytes uploaded
3333
+ * @param totalBytes - Total bytes to upload, null if unknown
3366
3334
  */
3367
- constructor(eventSource: EventSource<T>);
3335
+ handleUploadProgress(uploadId: string, bytesUploaded: number, totalBytes: number | null): void;
3368
3336
  /**
3369
- * Subscribe to events with optional filtering
3337
+ * Execute a flow with the provided input data.
3370
3338
  *
3371
- * @param handler - Callback function to invoke when matching events occur
3372
- * @param filter - Optional filter options to narrow down which events trigger the handler
3373
- * @returns Unsubscribe function to remove this specific subscription
3339
+ * The input type and execution behavior depends on the generic TInput type:
3340
+ * - File/Blob: Initiates chunked upload with progress tracking
3341
+ * - string (URL): Directly passes URL to flow for fetching
3342
+ * - object: Passes structured data to flow input nodes
3374
3343
  *
3375
- * @example Subscribe to specific event type
3344
+ * @param input - Input data for the flow execution (type determined by TInput generic)
3345
+ *
3346
+ * @example
3376
3347
  * ```typescript
3377
- * const unsubscribe = manager.subscribe(
3378
- * (event) => console.log('Progress:', event),
3379
- * { eventType: 'UPLOAD_PROGRESS' }
3380
- * );
3348
+ * // File upload
3349
+ * await manager.upload(fileObject);
3381
3350
  *
3382
- * // Later, unsubscribe
3383
- * unsubscribe();
3351
+ * // URL fetch
3352
+ * await manager.upload("https://example.com/image.jpg");
3384
3353
  * ```
3385
3354
  */
3386
- subscribe(handler: SubscriptionEventHandler<T>, filter?: EventFilterOptions): UnsubscribeFunction;
3355
+ upload(input: TInput): Promise<void>;
3387
3356
  /**
3388
- * Check if an event matches the filter criteria
3389
- *
3390
- * @param event - Event to check
3391
- * @param filter - Filter options to apply
3392
- * @returns True if the event passes all filters
3357
+ * Abort the current flow upload
3393
3358
  */
3394
- private shouldHandleEvent;
3359
+ abort(): void;
3395
3360
  /**
3396
- * Get the number of active subscriptions
3397
- *
3398
- * @returns Number of tracked subscriptions
3361
+ * Pause the current flow upload
3399
3362
  */
3400
- getSubscriptionCount(): number;
3363
+ pause(): void;
3401
3364
  /**
3402
- * Check if there are any active subscriptions
3403
- *
3404
- * @returns True if at least one subscription is active
3365
+ * Reset the flow upload state to idle
3405
3366
  */
3406
- hasSubscriptions(): boolean;
3367
+ reset(): void;
3407
3368
  /**
3408
- * Unsubscribe from all tracked subscriptions and clear the subscription list
3409
- *
3410
- * This is typically called when disposing of a component or cleaning up resources.
3369
+ * Aggregate progress across multiple inputs.
3370
+ * Uses simple average for Phase 1 (size-weighted can be added in Phase 2).
3371
+ */
3372
+ private aggregateProgress;
3373
+ /**
3374
+ * Execute a flow with multiple inputs (generic execution path).
3411
3375
  *
3412
- * @example Cleanup in framework hooks
3413
- * ```typescript
3414
- * // React
3415
- * useEffect(() => {
3416
- * const manager = new EventSubscriptionManager(eventSource);
3417
- * manager.subscribe(handler, filter);
3376
+ * This method:
3377
+ * 1. Builds FlowInputs with auto-detection
3378
+ * 2. Validates inputs (optional, to be added in integration)
3379
+ * 3. Executes flow with the inputs
3380
+ * 4. Tracks multi-input state
3418
3381
  *
3419
- * return () => manager.cleanup();
3420
- * }, []);
3382
+ * @param inputs - Map of nodeId to raw input data
3421
3383
  *
3422
- * // Vue
3423
- * onUnmounted(() => {
3424
- * manager.cleanup();
3384
+ * @example
3385
+ * ```typescript
3386
+ * await manager.executeFlow({
3387
+ * "file-input": myFile,
3388
+ * "url-input": "https://example.com/image.jpg"
3425
3389
  * });
3426
3390
  * ```
3427
3391
  */
3392
+ executeFlow(inputs: Record<string, unknown>): Promise<void>;
3393
+ /**
3394
+ * Get the input execution states (for multi-input flows).
3395
+ * @returns Map of nodeId to input state
3396
+ */
3397
+ getInputStates(): ReadonlyMap<string, InputExecutionState>;
3398
+ /**
3399
+ * Clean up resources (call when disposing the manager)
3400
+ */
3428
3401
  cleanup(): void;
3402
+ }
3403
+ //#endregion
3404
+ //#region src/types/upload-options.d.ts
3405
+ interface UploadOptions {
3429
3406
  /**
3430
- * Update the upload ID filter for all subscriptions that have an uploadId filter
3407
+ * Upload metadata to attach to the file
3408
+ */
3409
+ metadata?: Record<string, string>;
3410
+ /**
3411
+ * Whether to defer the upload size calculation
3412
+ */
3413
+ uploadLengthDeferred?: boolean;
3414
+ /**
3415
+ * Manual upload size override
3416
+ */
3417
+ uploadSize?: number;
3418
+ /**
3419
+ * Called when upload progress updates
3431
3420
  *
3432
- * This is useful when the current upload changes and you want to update
3433
- * all subscriptions to listen for the new upload's events.
3421
+ * @param uploadId - The unique identifier for this upload
3422
+ * @param bytesUploaded - Number of bytes uploaded so far
3423
+ * @param totalBytes - Total bytes to upload, null if unknown/deferred
3424
+ */
3425
+ onProgress?: (uploadId: string, bytesUploaded: number, totalBytes: number | null) => void;
3426
+ /**
3427
+ * Called when a chunk completes
3434
3428
  *
3435
- * @param newUploadId - New upload ID to filter events by
3429
+ * @param chunkSize - Size of the completed chunk in bytes
3430
+ * @param bytesAccepted - Total bytes accepted by server so far
3431
+ * @param bytesTotal - Total bytes to upload, null if unknown/deferred
3432
+ */
3433
+ onChunkComplete?: (chunkSize: number, bytesAccepted: number, bytesTotal: number | null) => void;
3434
+ /**
3435
+ * Called when upload succeeds
3436
3436
  *
3437
- * @example Update upload ID when starting new upload
3438
- * ```typescript
3439
- * const manager = new EventSubscriptionManager(eventSource);
3440
- * manager.subscribe(onProgress, { eventType: 'UPLOAD_PROGRESS', uploadId: null });
3437
+ * @param result - The uploaded file result
3438
+ */
3439
+ onSuccess?: (result: UploadFile$1) => void;
3440
+ /**
3441
+ * Called when upload fails
3441
3442
  *
3442
- * // When upload starts
3443
- * manager.updateUploadIdFilter(uploadId);
3444
- * ```
3443
+ * @param error - The error that caused the failure
3445
3444
  */
3446
- updateUploadIdFilter(newUploadId: string | null): void;
3447
- }
3448
- //#endregion
3449
- //#region src/managers/flow-manager.d.ts
3450
- /**
3451
- * Flow upload status representing the current state of a flow upload lifecycle.
3452
- * Flow uploads progress through: idle → uploading → processing → success/error/aborted
3453
- */
3454
- type FlowUploadStatus = "idle" | "uploading" | "processing" | "success" | "error" | "aborted";
3455
- /**
3456
- * Complete state information for a flow upload operation.
3457
- * Tracks both the upload phase (file transfer) and processing phase (flow execution).
3458
- */
3459
- interface FlowUploadState {
3460
- /** Current upload status */
3461
- status: FlowUploadStatus;
3462
- /** Upload progress percentage (0-100) */
3463
- progress: number;
3464
- /** Number of bytes uploaded */
3465
- bytesUploaded: number;
3466
- /** Total bytes to upload, null if unknown */
3467
- totalBytes: number | null;
3468
- /** Error if upload or processing failed */
3469
- error: Error | null;
3470
- /** Unique identifier for the flow execution job */
3471
- jobId: string | null;
3472
- /** Whether the flow processing has started */
3473
- flowStarted: boolean;
3474
- /** Name of the currently executing flow node */
3475
- currentNodeName: string | null;
3476
- /** Type of the currently executing flow node */
3477
- currentNodeType: string | null;
3445
+ onError?: (error: Error) => void;
3446
+ /**
3447
+ * Called when upload is aborted
3448
+ */
3449
+ onAbort?: () => void;
3478
3450
  /**
3479
- * Complete typed outputs from all output nodes in the flow.
3480
- * Each output includes nodeId, optional nodeType, data, and timestamp.
3481
- * Available when status is "success".
3451
+ * Custom retry logic
3452
+ *
3453
+ * @param error - The error that triggered the retry check
3454
+ * @param retryAttempt - The current retry attempt number (0-indexed)
3455
+ * @returns true to retry, false to fail
3482
3456
  */
3483
- flowOutputs: TypedOutput[] | null;
3457
+ onShouldRetry?: (error: Error, retryAttempt: number) => boolean;
3484
3458
  }
3459
+ //#endregion
3460
+ //#region src/managers/upload-manager.d.ts
3485
3461
  /**
3486
- * State for a single input in a multi-input flow.
3462
+ * Upload status representing the current state of an upload
3487
3463
  */
3488
- interface InputExecutionState {
3489
- /** Input node ID */
3490
- nodeId: string;
3491
- /** Input type (file, url, data) */
3492
- type: "file" | "url" | "data";
3493
- /** Current status of this input */
3494
- status: "pending" | "uploading" | "complete" | "error";
3495
- /** Progress percentage for file uploads (0-100) */
3464
+ type UploadStatus = "idle" | "uploading" | "success" | "error" | "aborted";
3465
+ /**
3466
+ * Complete upload state
3467
+ */
3468
+ interface UploadState {
3469
+ /** Current status of the upload */
3470
+ status: UploadStatus;
3471
+ /** Upload progress percentage (0-100) */
3496
3472
  progress: number;
3497
- /** Bytes uploaded for file uploads */
3473
+ /** Number of bytes uploaded */
3498
3474
  bytesUploaded: number;
3499
- /** Total bytes for file uploads */
3475
+ /** Total bytes to upload, null if unknown/deferred */
3500
3476
  totalBytes: number | null;
3501
- /** Error if this input failed */
3477
+ /** Error if upload failed */
3502
3478
  error: Error | null;
3503
- /** Abort controller for this specific input */
3504
- abortController: FlowUploadAbortController | null;
3479
+ /** Result if upload succeeded */
3480
+ result: UploadFile | null;
3505
3481
  }
3506
3482
  /**
3507
- * Callbacks that FlowManager invokes during the flow upload lifecycle
3483
+ * Callbacks that UploadManager invokes during the upload lifecycle
3508
3484
  */
3509
- interface FlowManagerCallbacks {
3485
+ interface UploadManagerCallbacks {
3510
3486
  /**
3511
- * Called when the flow upload state changes
3487
+ * Called when the upload state changes
3512
3488
  */
3513
- onStateChange: (state: FlowUploadState) => void;
3489
+ onStateChange: (state: UploadState) => void;
3514
3490
  /**
3515
3491
  * Called when upload progress updates
3516
- * @param progress - Progress percentage (0-100)
3492
+ * @param uploadId - The unique identifier for this upload
3517
3493
  * @param bytesUploaded - Number of bytes uploaded
3518
3494
  * @param totalBytes - Total bytes to upload, null if unknown
3519
3495
  */
@@ -3526,452 +3502,476 @@ interface FlowManagerCallbacks {
3526
3502
  */
3527
3503
  onChunkComplete?: (chunkSize: number, bytesAccepted: number, bytesTotal: number | null) => void;
3528
3504
  /**
3529
- * Called when the flow completes successfully (receives full flow outputs)
3530
- * Each output includes nodeId, optional nodeType (e.g., "storage-output-v1"), data, and timestamp.
3531
- *
3532
- * @param outputs - Array of typed outputs from all output nodes
3533
- *
3534
- * @example
3535
- * ```typescript
3536
- * onFlowComplete: (outputs) => {
3537
- * for (const output of outputs) {
3538
- * console.log(`${output.nodeId} (${output.nodeType}):`, output.data);
3539
- * }
3540
- * }
3541
- * ```
3542
- */
3543
- onFlowComplete?: (outputs: TypedOutput[]) => void;
3544
- /**
3545
- * Called when upload succeeds (receives typed outputs from all output nodes)
3546
- * Each output includes nodeId, optional nodeType (e.g., "storage-output-v1"), data, and timestamp.
3547
- *
3548
- * @param outputs - Array of typed outputs from all output nodes
3549
- *
3550
- * @example
3551
- * ```typescript
3552
- * onSuccess: (outputs) => {
3553
- * for (const output of outputs) {
3554
- * console.log(`${output.nodeId} completed:`, output.data);
3555
- * }
3556
- * }
3557
- * ```
3505
+ * Called when upload completes successfully
3506
+ * @param result - The uploaded file result
3558
3507
  */
3559
- onSuccess?: (outputs: TypedOutput[]) => void;
3508
+ onSuccess?: (result: UploadFile) => void;
3560
3509
  /**
3561
- * Called when upload or flow processing fails with an error
3510
+ * Called when upload fails with an error
3562
3511
  * @param error - The error that occurred
3563
3512
  */
3564
3513
  onError?: (error: Error) => void;
3565
3514
  /**
3566
- * Called when upload or flow is aborted
3515
+ * Called when upload is aborted
3567
3516
  */
3568
3517
  onAbort?: () => void;
3569
3518
  }
3570
3519
  /**
3571
- * Generic flow execution input type - can be any value that the flow execution client accepts.
3572
- * Common types include File, Blob, string (for URLs), or structured data objects.
3573
- *
3574
- * @remarks
3575
- * The flexibility of this type enables different flow execution patterns:
3576
- * - File/Blob: Traditional chunked file upload with init/finalize operations
3577
- * - string (URL): Direct file fetch from external URL
3578
- * - object: Structured data for non-file input nodes (future)
3579
- */
3580
- type FlowUploadInput = unknown;
3581
- /**
3582
- * Flow configuration for upload
3583
- */
3584
- interface FlowConfig {
3585
- flowId: string;
3586
- storageId: string;
3587
- outputNodeId?: string;
3588
- metadata?: Record<string, string>;
3589
- }
3590
- /**
3591
- * Abort and pause controller interface for canceling/pausing flow uploads
3592
- */
3593
- interface FlowUploadAbortController {
3594
- abort: () => void | Promise<void>;
3595
- pause: () => void | Promise<void>;
3596
- }
3597
- /**
3598
- * Internal upload options used by the flow upload function.
3599
- * The upload phase always returns UploadFile, regardless of the final TOutput type.
3600
- */
3601
- interface InternalFlowUploadOptions {
3602
- onJobStart?: (jobId: string) => void;
3603
- onProgress?: (uploadId: string, bytesUploaded: number, totalBytes: number | null) => void;
3604
- onChunkComplete?: (chunkSize: number, bytesAccepted: number, bytesTotal: number | null) => void;
3605
- onSuccess?: (result: UploadFile) => void;
3606
- onError?: (error: Error) => void;
3607
- onAbort?: () => void;
3608
- onShouldRetry?: (error: Error, retryAttempt: number) => boolean;
3609
- }
3610
- /**
3611
- * Flow upload function that performs the actual upload with flow processing.
3612
- * Returns a promise that resolves to an abort controller with pause capability.
3613
- *
3614
- * Note: The upload phase onSuccess always receives UploadFile. The final TOutput
3615
- * result comes from the flow execution and is handled via FlowEnd events.
3520
+ * Generic upload input type - can be any value that the upload client accepts
3616
3521
  */
3617
- type FlowUploadFunction<TInput = FlowUploadInput> = (input: TInput, flowConfig: FlowConfig, options: InternalFlowUploadOptions) => Promise<FlowUploadAbortController>;
3522
+ type UploadInput = unknown;
3618
3523
  /**
3619
- * Callbacks for tracking individual input progress in multi-input flows
3524
+ * Abort controller interface for canceling uploads
3620
3525
  */
3621
- interface MultiInputCallbacks {
3622
- /**
3623
- * Called when an input's progress updates
3624
- * @param nodeId - The input node ID
3625
- * @param progress - Progress percentage (0-100)
3626
- * @param bytesUploaded - Bytes uploaded for this input
3627
- * @param totalBytes - Total bytes for this input
3628
- */
3629
- onInputProgress?: (nodeId: string, progress: number, bytesUploaded: number, totalBytes: number | null) => void;
3630
- /**
3631
- * Called when an input completes successfully
3632
- * @param nodeId - The input node ID
3633
- */
3634
- onInputComplete?: (nodeId: string) => void;
3635
- /**
3636
- * Called when an input fails
3637
- * @param nodeId - The input node ID
3638
- * @param error - The error that occurred
3639
- */
3640
- onInputError?: (nodeId: string, error: Error) => void;
3526
+ interface UploadAbortController {
3527
+ abort: () => void;
3641
3528
  }
3642
3529
  /**
3643
- * Multi-input flow upload function that coordinates multiple inputs in a single flow.
3644
- * Platform packages should implement this to enable parallel multi-input upload support.
3645
- *
3646
- * @param inputs - Record of nodeId to input data (File, URL string, or structured data)
3647
- * @param flowConfig - Flow configuration
3648
- * @param options - Upload callbacks and configuration
3649
- * @param multiInputCallbacks - Per-input progress tracking callbacks
3650
- * @returns Promise resolving to abort controller for the entire flow execution
3651
- *
3652
- * @example
3653
- * ```typescript
3654
- * const uploadFn: MultiInputFlowUploadFunction = async (inputs, flowConfig, options, callbacks) => {
3655
- * // 1. Start flow and create job
3656
- * const jobId = await startFlow(flowConfig.flowId, flowConfig.storageId);
3657
- *
3658
- * // 2. Initialize all inputs in parallel using orchestrator functions
3659
- * const initPromises = Object.entries(inputs).map(([nodeId, data]) =>
3660
- * initializeFlowInput({ nodeId, jobId, source: data, ... })
3661
- * );
3662
- *
3663
- * // 3. Upload files in parallel
3664
- * // 4. Finalize all inputs
3665
- * // 5. Return abort controller
3666
- * };
3667
- * ```
3530
+ * Upload function that performs the actual upload.
3531
+ * Returns a promise that resolves to an abort controller.
3668
3532
  */
3669
- type MultiInputFlowUploadFunction = (inputs: Record<string, unknown>, flowConfig: FlowConfig, options: InternalFlowUploadOptions, multiInputCallbacks?: MultiInputCallbacks) => Promise<FlowUploadAbortController>;
3533
+ type UploadFunction<TInput = UploadInput, TOptions extends UploadOptions = UploadOptions> = (input: TInput, options: TOptions) => Promise<UploadAbortController>;
3670
3534
  /**
3671
- * Platform-agnostic flow execution manager that handles flow state machine,
3672
- * progress tracking, flow event handling, error handling, abort, pause, reset, and retry logic.
3673
- *
3674
- * Supports multiple input types through generic TInput parameter:
3675
- * - File/Blob: Chunked file upload with progress tracking
3676
- * - string (URL): Direct file fetch from external source
3677
- * - object: Structured data for custom input nodes
3535
+ * Platform-agnostic upload manager that handles upload state machine,
3536
+ * progress tracking, error handling, abort, reset, and retry logic.
3678
3537
  *
3679
3538
  * Framework packages (React, Vue, React Native) should wrap this manager
3680
3539
  * with framework-specific hooks/composables.
3681
3540
  *
3682
- * @template TInput - The type of input data accepted by the flow (File, Blob, string, object, etc.)
3683
- *
3684
3541
  * @example
3685
3542
  * ```typescript
3686
- * // File upload flow
3687
- * const fileFlowManager = new FlowManager<File>(...);
3688
- * await fileFlowManager.upload(myFile);
3689
- *
3690
- * // URL fetch flow
3691
- * const urlFlowManager = new FlowManager<string>(...);
3692
- * await urlFlowManager.upload("https://example.com/image.jpg");
3543
+ * const uploadFn = (input, options) => client.upload(input, options);
3544
+ * const manager = new UploadManager(uploadFn, {
3545
+ * onStateChange: (state) => setState(state),
3546
+ * onProgress: (progress) => console.log(`${progress}%`),
3547
+ * onSuccess: (result) => console.log('Upload complete:', result),
3548
+ * onError: (error) => console.error('Upload failed:', error),
3549
+ * });
3693
3550
  *
3694
- * // Structured data flow
3695
- * const dataFlowManager = new FlowManager<{ text: string }>(...);
3696
- * await dataFlowManager.upload({ text: "Process this" });
3551
+ * await manager.upload(file);
3697
3552
  * ```
3698
3553
  */
3699
- declare class FlowManager<TInput = FlowUploadInput> {
3700
- private readonly flowUploadFn;
3554
+ declare class UploadManager<TInput = UploadInput, TOptions extends UploadOptions = UploadOptions> {
3555
+ private readonly uploadFn;
3701
3556
  private readonly callbacks;
3702
- private readonly options;
3703
- private readonly multiInputUploadFn?;
3557
+ private readonly options?;
3704
3558
  private state;
3705
3559
  private abortController;
3706
- private inputStates;
3707
- /** Tracks the nodeId when executing a single-input flow via executeFlow() */
3708
- private currentSingleInputNodeId;
3560
+ private lastInput;
3561
+ private uploadId;
3709
3562
  /**
3710
- * Create a new FlowManager
3563
+ * Create a new UploadManager
3711
3564
  *
3712
- * @param flowUploadFn - Flow upload function to use for uploads
3713
- * @param callbacks - Callbacks to invoke during flow upload lifecycle
3714
- * @param options - Flow upload configuration options
3715
- * @param multiInputUploadFn - Optional multi-input upload function for executeFlow()
3716
- */
3717
- constructor(flowUploadFn: FlowUploadFunction<TInput>, callbacks: FlowManagerCallbacks, options: FlowUploadOptions, multiInputUploadFn?: MultiInputFlowUploadFunction | undefined);
3718
- /**
3719
- * Get the current flow upload state
3720
- */
3721
- getState(): FlowUploadState;
3722
- /**
3723
- * Check if an upload or flow is currently active
3724
- */
3725
- isUploading(): boolean;
3726
- /**
3727
- * Check if file upload is in progress
3728
- */
3729
- isUploadingFile(): boolean;
3730
- /**
3731
- * Check if flow processing is in progress
3565
+ * @param uploadFn - Upload function to use for uploads
3566
+ * @param callbacks - Callbacks to invoke during upload lifecycle
3567
+ * @param options - Upload configuration options
3732
3568
  */
3733
- isProcessing(): boolean;
3569
+ constructor(uploadFn: UploadFunction<TInput, TOptions>, callbacks: UploadManagerCallbacks, options?: TOptions | undefined);
3734
3570
  /**
3735
- * Get the current job ID
3571
+ * Get the current upload state
3736
3572
  */
3737
- getJobId(): string | null;
3573
+ getState(): UploadState;
3738
3574
  /**
3739
- * Update the internal state and notify callbacks
3575
+ * Check if an upload is currently active
3740
3576
  */
3741
- private updateState;
3577
+ isUploading(): boolean;
3742
3578
  /**
3743
- * Handle flow events from the event subscription
3744
- * This method should be called by the framework wrapper when it receives flow events
3745
- *
3746
- * @param event - Flow event to process
3579
+ * Check if the upload can be retried
3747
3580
  */
3748
- handleFlowEvent(event: FlowEvent): void;
3581
+ canRetry(): boolean;
3749
3582
  /**
3750
- * Handle upload progress events from the event subscription
3751
- * This method should be called by the framework wrapper when it receives upload progress events
3752
- *
3753
- * @param uploadId - The unique identifier for this upload
3754
- * @param bytesUploaded - Number of bytes uploaded
3755
- * @param totalBytes - Total bytes to upload, null if unknown
3583
+ * Update the internal state and notify callbacks
3756
3584
  */
3757
- handleUploadProgress(uploadId: string, bytesUploaded: number, totalBytes: number | null): void;
3585
+ private updateState;
3758
3586
  /**
3759
- * Execute a flow with the provided input data.
3760
- *
3761
- * The input type and execution behavior depends on the generic TInput type:
3762
- * - File/Blob: Initiates chunked upload with progress tracking
3763
- * - string (URL): Directly passes URL to flow for fetching
3764
- * - object: Passes structured data to flow input nodes
3765
- *
3766
- * @param input - Input data for the flow execution (type determined by TInput generic)
3767
- *
3768
- * @example
3769
- * ```typescript
3770
- * // File upload
3771
- * await manager.upload(fileObject);
3587
+ * Start uploading a file or input
3772
3588
  *
3773
- * // URL fetch
3774
- * await manager.upload("https://example.com/image.jpg");
3775
- * ```
3589
+ * @param input - File or input to upload (type depends on platform)
3776
3590
  */
3777
3591
  upload(input: TInput): Promise<void>;
3778
3592
  /**
3779
- * Abort the current flow upload
3593
+ * Abort the current upload
3780
3594
  */
3781
3595
  abort(): void;
3782
3596
  /**
3783
- * Pause the current flow upload
3784
- */
3785
- pause(): void;
3786
- /**
3787
- * Reset the flow upload state to idle
3597
+ * Reset the upload state to idle
3788
3598
  */
3789
3599
  reset(): void;
3790
3600
  /**
3791
- * Aggregate progress across multiple inputs.
3792
- * Uses simple average for Phase 1 (size-weighted can be added in Phase 2).
3793
- */
3794
- private aggregateProgress;
3795
- /**
3796
- * Execute a flow with multiple inputs (generic execution path).
3797
- *
3798
- * This method:
3799
- * 1. Builds FlowInputs with auto-detection
3800
- * 2. Validates inputs (optional, to be added in integration)
3801
- * 3. Executes flow with the inputs
3802
- * 4. Tracks multi-input state
3803
- *
3804
- * @param inputs - Map of nodeId to raw input data
3805
- *
3806
- * @example
3807
- * ```typescript
3808
- * await manager.executeFlow({
3809
- * "file-input": myFile,
3810
- * "url-input": "https://example.com/image.jpg"
3811
- * });
3812
- * ```
3813
- */
3814
- executeFlow(inputs: Record<string, unknown>): Promise<void>;
3815
- /**
3816
- * Get the input execution states (for multi-input flows).
3817
- * @returns Map of nodeId to input state
3601
+ * Retry the last failed or aborted upload
3818
3602
  */
3819
- getInputStates(): ReadonlyMap<string, InputExecutionState>;
3603
+ retry(): void;
3820
3604
  /**
3821
3605
  * Clean up resources (call when disposing the manager)
3822
3606
  */
3823
3607
  cleanup(): void;
3824
3608
  }
3825
3609
  //#endregion
3826
- //#region src/managers/upload-manager.d.ts
3610
+ //#region src/storage/in-memory-storage-service.d.ts
3827
3611
  /**
3828
- * Upload status representing the current state of an upload
3612
+ * In-memory fallback storage service for Expo
3613
+ * Used when AsyncStorage is not available or for testing
3829
3614
  */
3830
- type UploadStatus = "idle" | "uploading" | "success" | "error" | "aborted";
3615
+ declare function createInMemoryStorageService(): StorageService;
3616
+ //#endregion
3617
+ //#region src/types/flow-inputs.d.ts
3831
3618
  /**
3832
- * Complete upload state
3619
+ * Type definitions for flexible flow input specifications.
3620
+ *
3621
+ * This module defines types for passing input data to flows with multiple input nodes.
3622
+ * The FlowInputs type maps node IDs to their respective input data, enabling support
3623
+ * for flows with single or multiple input points.
3624
+ *
3625
+ * @module types/flow-inputs
3626
+ *
3627
+ * @example
3628
+ * ```typescript
3629
+ * import type { FlowInputs } from "@uploadista/client-core";
3630
+ *
3631
+ * // Single input flow
3632
+ * const inputs: FlowInputs = {
3633
+ * "file-input": {
3634
+ * operation: "url",
3635
+ * url: "https://example.com/image.jpg"
3636
+ * }
3637
+ * };
3638
+ *
3639
+ * // Multi-input flow
3640
+ * const multiInputs: FlowInputs = {
3641
+ * "file-input": {
3642
+ * operation: "init",
3643
+ * storageId: "s3",
3644
+ * metadata: { originalName: "image.jpg" }
3645
+ * },
3646
+ * "metadata-input": {
3647
+ * title: "My Image",
3648
+ * tags: ["photo", "landscape"]
3649
+ * }
3650
+ * };
3651
+ * ```
3833
3652
  */
3834
- interface UploadState {
3835
- /** Current status of the upload */
3836
- status: UploadStatus;
3837
- /** Upload progress percentage (0-100) */
3653
+ /**
3654
+ * Flow input specification mapping node IDs to their input data.
3655
+ *
3656
+ * This type represents a map of input node IDs to their respective input data.
3657
+ * Each key is a node ID, and each value is the data to pass to that node.
3658
+ * The data structure depends on the node's registered input type.
3659
+ *
3660
+ * @remarks
3661
+ * Input data is validated against each node's registered type schema before
3662
+ * flow execution begins. Invalid data will result in validation errors.
3663
+ *
3664
+ * @example
3665
+ * ```typescript
3666
+ * // For streaming input node (init operation)
3667
+ * const fileUploadInputs: FlowInputs = {
3668
+ * "input-node-1": {
3669
+ * operation: "init",
3670
+ * storageId: "my-storage",
3671
+ * metadata: {
3672
+ * originalName: "photo.jpg",
3673
+ * mimeType: "image/jpeg",
3674
+ * size: 1024000
3675
+ * }
3676
+ * }
3677
+ * };
3678
+ *
3679
+ * // For streaming input node (URL operation)
3680
+ * const urlInputs: FlowInputs = {
3681
+ * "input-node-1": {
3682
+ * operation: "url",
3683
+ * url: "https://example.com/photo.jpg",
3684
+ * storageId: "my-storage",
3685
+ * metadata: {
3686
+ * source: "external"
3687
+ * }
3688
+ * }
3689
+ * };
3690
+ * ```
3691
+ */
3692
+ type FlowInputs = Record<string, unknown>;
3693
+ /**
3694
+ * Helper type for single-input flows.
3695
+ *
3696
+ * Many flows have exactly one input node. This helper type makes it easier
3697
+ * to work with single-input scenarios without needing to know the node ID upfront.
3698
+ *
3699
+ * @example
3700
+ * ```typescript
3701
+ * const singleInput: SingleFlowInput = {
3702
+ * operation: "url",
3703
+ * url: "https://example.com/image.jpg"
3704
+ * };
3705
+ *
3706
+ * // The client can auto-discover the input node ID and convert this to FlowInputs
3707
+ * ```
3708
+ */
3709
+ type SingleFlowInput = unknown;
3710
+ /**
3711
+ * Result of input node discovery.
3712
+ *
3713
+ * Contains information about discovered input nodes in a flow, including
3714
+ * their IDs, types, and whether the flow has a single or multiple inputs.
3715
+ *
3716
+ * @property inputNodes - Array of input node information
3717
+ * @property single - True if flow has exactly one input node
3718
+ */
3719
+ interface InputNodeDiscovery {
3720
+ inputNodes: Array<{
3721
+ id: string;
3722
+ type: string;
3723
+ name?: string;
3724
+ }>;
3725
+ single: boolean;
3726
+ }
3727
+ //#endregion
3728
+ //#region src/types/flow-result.d.ts
3729
+ type FlowResult<TOutput = UploadFile> = {
3730
+ type: "success";
3731
+ value: TOutput;
3732
+ } | {
3733
+ type: "error";
3734
+ error: Error;
3735
+ } | {
3736
+ type: "cancelled";
3737
+ };
3738
+ //#endregion
3739
+ //#region src/types/flow-upload-item.d.ts
3740
+ /**
3741
+ * Flow upload item for multi-flow-upload tracking
3742
+ */
3743
+ interface FlowUploadItem<UploadInput$1> {
3744
+ id: string;
3745
+ file: UploadInput$1;
3746
+ status: "pending" | "uploading" | "success" | "error" | "aborted";
3838
3747
  progress: number;
3839
- /** Number of bytes uploaded */
3840
3748
  bytesUploaded: number;
3841
- /** Total bytes to upload, null if unknown/deferred */
3842
- totalBytes: number | null;
3843
- /** Error if upload failed */
3749
+ totalBytes: number;
3844
3750
  error: Error | null;
3845
- /** Result if upload succeeded */
3846
- result: UploadFile | null;
3751
+ result: UploadFile$1 | null;
3752
+ jobId: string | null;
3847
3753
  }
3848
- /**
3849
- * Callbacks that UploadManager invokes during the upload lifecycle
3850
- */
3851
- interface UploadManagerCallbacks {
3754
+ //#endregion
3755
+ //#region src/types/multi-flow-upload-options.d.ts
3756
+ interface MultiFlowUploadOptions<UploadInput$1> {
3852
3757
  /**
3853
- * Called when the upload state changes
3758
+ * Flow configuration
3854
3759
  */
3855
- onStateChange: (state: UploadState) => void;
3760
+ flowConfig: FlowUploadConfig;
3856
3761
  /**
3857
- * Called when upload progress updates
3858
- * @param uploadId - The unique identifier for this upload
3859
- * @param bytesUploaded - Number of bytes uploaded
3860
- * @param totalBytes - Total bytes to upload, null if unknown
3762
+ * Maximum number of concurrent uploads (default: 3)
3861
3763
  */
3862
- onProgress?: (uploadId: string, bytesUploaded: number, totalBytes: number | null) => void;
3764
+ maxConcurrent?: number;
3863
3765
  /**
3864
- * Called when a chunk completes
3865
- * @param chunkSize - Size of the completed chunk
3866
- * @param bytesAccepted - Total bytes accepted so far
3867
- * @param bytesTotal - Total bytes to upload, null if unknown
3766
+ * Called when an individual upload progresses
3767
+ */
3768
+ onItemProgress?: (item: FlowUploadItem<UploadInput$1>) => void;
3769
+ /**
3770
+ * Called when an individual upload succeeds
3868
3771
  */
3869
- onChunkComplete?: (chunkSize: number, bytesAccepted: number, bytesTotal: number | null) => void;
3772
+ onItemSuccess?: (item: FlowUploadItem<UploadInput$1>) => void;
3870
3773
  /**
3871
- * Called when upload completes successfully
3872
- * @param result - The uploaded file result
3774
+ * Called when an individual upload fails
3873
3775
  */
3874
- onSuccess?: (result: UploadFile) => void;
3776
+ onItemError?: (item: FlowUploadItem<UploadInput$1>, error: Error) => void;
3875
3777
  /**
3876
- * Called when upload fails with an error
3877
- * @param error - The error that occurred
3778
+ * Called when all uploads complete
3878
3779
  */
3879
- onError?: (error: Error) => void;
3780
+ onComplete?: (items: FlowUploadItem<UploadInput$1>[]) => void;
3880
3781
  /**
3881
- * Called when upload is aborted
3782
+ * Custom retry logic
3882
3783
  */
3883
- onAbort?: () => void;
3784
+ onShouldRetry?: (error: Error, retryAttempt: number) => boolean;
3884
3785
  }
3885
- /**
3886
- * Generic upload input type - can be any value that the upload client accepts
3887
- */
3888
- type UploadInput = unknown;
3889
- /**
3890
- * Abort controller interface for canceling uploads
3891
- */
3892
- interface UploadAbortController {
3893
- abort: () => void;
3786
+ //#endregion
3787
+ //#region src/types/multi-flow-upload-state.d.ts
3788
+ interface MultiFlowUploadState<UploadInput$1> {
3789
+ items: FlowUploadItem<UploadInput$1>[];
3790
+ totalProgress: number;
3791
+ activeUploads: number;
3792
+ completedUploads: number;
3793
+ failedUploads: number;
3894
3794
  }
3795
+ //#endregion
3796
+ //#region src/types/upload-metrics.d.ts
3895
3797
  /**
3896
- * Upload function that performs the actual upload.
3897
- * Returns a promise that resolves to an abort controller.
3898
- */
3899
- type UploadFunction<TInput = UploadInput, TOptions extends UploadOptions = UploadOptions> = (input: TInput, options: TOptions) => Promise<UploadAbortController>;
3900
- /**
3901
- * Platform-agnostic upload manager that handles upload state machine,
3902
- * progress tracking, error handling, abort, reset, and retry logic.
3798
+ * Comprehensive upload metrics interface
3903
3799
  *
3904
- * Framework packages (React, Vue, React Native) should wrap this manager
3905
- * with framework-specific hooks/composables.
3800
+ * Provides access to all performance metrics, insights, and network
3801
+ * statistics for upload monitoring and optimization.
3906
3802
  *
3907
- * @example
3908
- * ```typescript
3909
- * const uploadFn = (input, options) => client.upload(input, options);
3910
- * const manager = new UploadManager(uploadFn, {
3911
- * onStateChange: (state) => setState(state),
3912
- * onProgress: (progress) => console.log(`${progress}%`),
3913
- * onSuccess: (result) => console.log('Upload complete:', result),
3914
- * onError: (error) => console.error('Upload failed:', error),
3915
- * });
3803
+ * This interface is implemented by all framework packages (React, Vue, React Native)
3804
+ * to ensure consistent metrics API across platforms.
3916
3805
  *
3917
- * await manager.upload(file);
3806
+ * @example React usage
3807
+ * ```tsx
3808
+ * const upload = useUpload();
3809
+ * const insights = upload.metrics.getInsights();
3810
+ * const metrics = upload.metrics.exportMetrics();
3811
+ * ```
3812
+ *
3813
+ * @example Vue usage
3814
+ * ```vue
3815
+ * <script setup>
3816
+ * const upload = useUpload();
3817
+ * const insights = upload.metrics.getInsights();
3818
+ * </script>
3819
+ * ```
3820
+ *
3821
+ * @example React Native usage
3822
+ * ```tsx
3823
+ * const upload = useUpload();
3824
+ * const networkMetrics = upload.metrics.getNetworkMetrics();
3918
3825
  * ```
3919
3826
  */
3920
- declare class UploadManager<TInput = UploadInput, TOptions extends UploadOptions = UploadOptions> {
3921
- private readonly uploadFn;
3922
- private readonly callbacks;
3923
- private readonly options?;
3924
- private state;
3925
- private abortController;
3926
- private lastInput;
3927
- private uploadId;
3827
+ interface UploadMetrics {
3928
3828
  /**
3929
- * Create a new UploadManager
3829
+ * Get performance insights from the upload client
3930
3830
  *
3931
- * @param uploadFn - Upload function to use for uploads
3932
- * @param callbacks - Callbacks to invoke during upload lifecycle
3933
- * @param options - Upload configuration options
3934
- */
3935
- constructor(uploadFn: UploadFunction<TInput, TOptions>, callbacks: UploadManagerCallbacks, options?: TOptions | undefined);
3936
- /**
3937
- * Get the current upload state
3938
- */
3939
- getState(): UploadState;
3940
- /**
3941
- * Check if an upload is currently active
3942
- */
3943
- isUploading(): boolean;
3944
- /**
3945
- * Check if the upload can be retried
3946
- */
3947
- canRetry(): boolean;
3948
- /**
3949
- * Update the internal state and notify callbacks
3950
- */
3951
- private updateState;
3952
- /**
3953
- * Start uploading a file or input
3831
+ * Provides high-level analysis with recommendations for
3832
+ * optimizing upload performance.
3954
3833
  *
3955
- * @param input - File or input to upload (type depends on platform)
3834
+ * @returns Performance insights including efficiency scores and recommendations
3835
+ *
3836
+ * @example
3837
+ * ```typescript
3838
+ * const insights = metrics.getInsights();
3839
+ * console.log(`Efficiency: ${insights.overallEfficiency}%`);
3840
+ * console.log(`Recommendations:`, insights.recommendations);
3841
+ * ```
3956
3842
  */
3957
- upload(input: TInput): Promise<void>;
3843
+ getInsights: () => PerformanceInsights;
3958
3844
  /**
3959
- * Abort the current upload
3845
+ * Export detailed metrics from the upload client
3846
+ *
3847
+ * Returns comprehensive metrics including session data,
3848
+ * per-chunk statistics, and performance insights.
3849
+ *
3850
+ * Useful for analytics, debugging, and performance monitoring.
3851
+ *
3852
+ * @returns Object containing session metrics, chunk metrics, and insights
3853
+ *
3854
+ * @example
3855
+ * ```typescript
3856
+ * const metrics = metrics.exportMetrics();
3857
+ * console.log(`Uploaded ${metrics.session.totalBytesUploaded} bytes`);
3858
+ * console.log(`Average speed: ${metrics.session.averageSpeed} B/s`);
3859
+ * console.log(`Chunks: ${metrics.chunks.length}`);
3860
+ * ```
3960
3861
  */
3961
- abort(): void;
3862
+ exportMetrics: () => {
3863
+ /** Session-level aggregated metrics */
3864
+ session: Partial<UploadSessionMetrics>;
3865
+ /** Per-chunk detailed metrics */
3866
+ chunks: ChunkMetrics[];
3867
+ /** Performance insights and recommendations */
3868
+ insights: PerformanceInsights;
3869
+ };
3962
3870
  /**
3963
- * Reset the upload state to idle
3871
+ * Get current network metrics
3872
+ *
3873
+ * Provides real-time network statistics including speed,
3874
+ * errors, and network condition assessment.
3875
+ *
3876
+ * @returns Current network performance metrics
3877
+ *
3878
+ * @example
3879
+ * ```typescript
3880
+ * const network = metrics.getNetworkMetrics();
3881
+ * console.log(`Speed: ${network.currentSpeed} B/s`);
3882
+ * console.log(`Quality: ${network.condition.quality}`);
3883
+ * ```
3964
3884
  */
3965
- reset(): void;
3885
+ getNetworkMetrics: () => NetworkMetrics;
3966
3886
  /**
3967
- * Retry the last failed or aborted upload
3887
+ * Get current network condition
3888
+ *
3889
+ * Provides assessment of current network quality with
3890
+ * recommendations for adaptive upload strategies.
3891
+ *
3892
+ * @returns Network condition assessment
3893
+ *
3894
+ * @example
3895
+ * ```typescript
3896
+ * const condition = metrics.getNetworkCondition();
3897
+ * if (condition.quality === 'poor') {
3898
+ * console.log('Consider reducing chunk size');
3899
+ * }
3900
+ * ```
3968
3901
  */
3969
- retry(): void;
3902
+ getNetworkCondition: () => NetworkCondition;
3970
3903
  /**
3971
- * Clean up resources (call when disposing the manager)
3904
+ * Reset all metrics
3905
+ *
3906
+ * Clears all accumulated metrics and resets counters.
3907
+ * Useful when starting a new upload session.
3908
+ *
3909
+ * @example
3910
+ * ```typescript
3911
+ * // Reset metrics before starting new upload
3912
+ * metrics.resetMetrics();
3913
+ * upload(newFile);
3914
+ * ```
3972
3915
  */
3973
- cleanup(): void;
3916
+ resetMetrics: () => void;
3974
3917
  }
3975
3918
  //#endregion
3919
+ //#region src/types/upload-result.d.ts
3920
+ /**
3921
+ * Discriminated union representing the result of an upload operation.
3922
+ *
3923
+ * Provides a type-safe way to handle the three possible outcomes of an upload:
3924
+ * success, error, or cancellation. This pattern enables exhaustive checking
3925
+ * of all cases at compile time.
3926
+ *
3927
+ * @template TOutput - The type of the successful result value. Defaults to UploadFile
3928
+ *
3929
+ * @example Handling upload results
3930
+ * ```typescript
3931
+ * function handleUploadResult(result: UploadResult) {
3932
+ * switch (result.type) {
3933
+ * case 'success':
3934
+ * console.log('Upload complete:', result.value.id);
3935
+ * break;
3936
+ * case 'error':
3937
+ * console.error('Upload failed:', result.error.message);
3938
+ * break;
3939
+ * case 'cancelled':
3940
+ * console.log('Upload was cancelled by user');
3941
+ * break;
3942
+ * }
3943
+ * }
3944
+ * ```
3945
+ *
3946
+ * @example With custom output type
3947
+ * ```typescript
3948
+ * interface ProcessedImage {
3949
+ * url: string;
3950
+ * width: number;
3951
+ * height: number;
3952
+ * }
3953
+ *
3954
+ * const result: UploadResult<ProcessedImage> = await uploadAndProcess(file);
3955
+ *
3956
+ * if (result.type === 'success') {
3957
+ * console.log(`Image processed: ${result.value.width}x${result.value.height}`);
3958
+ * }
3959
+ * ```
3960
+ */
3961
+ type UploadResult<TOutput = UploadFile$1> = {
3962
+ /** Indicates the upload completed successfully */
3963
+ type: "success";
3964
+ /** The successful result value (e.g., upload metadata or processed output) */
3965
+ value: TOutput;
3966
+ } | {
3967
+ /** Indicates the upload failed with an error */
3968
+ type: "error";
3969
+ /** The error that caused the upload to fail */
3970
+ error: Error;
3971
+ } | {
3972
+ /** Indicates the upload was cancelled by the user or application */
3973
+ type: "cancelled";
3974
+ };
3975
+ //#endregion
3976
3976
  export { AbortControllerFactory, AbortControllerLike, AbortSignalLike, Base64Service, ChecksumService, ChunkBuffer, ChunkBufferConfig, ChunkMetrics, ClientStorage, ConnectionHealth, ConnectionMetrics, ConnectionPoolConfig, DetailedConnectionMetrics, type EventFilterOptions, type EventSource, EventSubscriptionManager, FileReaderService, FileSource, FingerprintService, type FlowConfig, FlowInputs, FlowManager, type FlowManagerCallbacks, FlowResponse, FlowResult, type FlowUploadAbortController, FlowUploadConfig, type FlowUploadFunction, type FlowUploadInput, FlowUploadItem, FlowUploadOptions, type FlowUploadState, type FlowUploadStatus, type GenericEvent, HeadersLike, Http2Info, HttpClient, HttpRequestOptions, HttpResponse, IdGenerationService, type InputExecutionState, InputNodeDiscovery, type InternalFlowUploadOptions, LogFunction, Logger, MultiFlowUploadOptions, MultiFlowUploadState, type MultiInputCallbacks, type MultiInputFlowUploadFunction, NetworkCondition, NetworkMetrics, NetworkMonitor, NetworkMonitorConfig, PerformanceInsights, PlatformService, PreviousUpload, RequestBody, ServiceContainer, SingleFlowInput, SliceResult, StorageService, type SubscriptionEventHandler, Timeout, type UnsubscribeFunction, type UploadAbortController, type UploadFunction, type UploadInput, UploadManager, type UploadManagerCallbacks, UploadMetrics, UploadOptions, UploadResponse, UploadResult, UploadSample, UploadSessionMetrics, type UploadState, type UploadStatus, UploadistaApi, UploadistaClient, UploadistaClientOptions, UploadistaDeleteUploadResponse, UploadistaError, UploadistaErrorName, UploadistaEvent, UploadistaUploadOptions, UploadistaUploadResponse, UploadistaWebSocketEventHandler, UploadistaWebSocketManager, UploadistaWebSocketMessage, WebSocketEventMap, WebSocketFactory, WebSocketLike, createClientStorage, createInMemoryStorageService, createLogger, createUploadistaApi, createUploadistaClient, defaultConnectionPoolingConfig, previousUploadSchema, wait };
3977
3977
  //# sourceMappingURL=index.d.mts.map