@uploadista/react 0.0.15-beta.4 → 0.0.15
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/components/index.d.mts +2 -2
- package/dist/components/index.mjs +1 -1
- package/dist/hooks/index.d.mts +2 -2
- package/dist/hooks/index.mjs +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{upload-zone-pXt4LdcC.mjs → upload-zone-DN7Gem65.mjs} +2 -2
- package/dist/{upload-zone-pXt4LdcC.mjs.map → upload-zone-DN7Gem65.mjs.map} +1 -1
- package/dist/{uploadista-provider-k2P1_Ms-.d.mts → uploadista-provider-DIMEpwsu.d.mts} +2 -2
- package/dist/{uploadista-provider-k2P1_Ms-.d.mts.map → uploadista-provider-DIMEpwsu.d.mts.map} +1 -1
- package/dist/use-upload-C7QZSt1M.mjs +2 -0
- package/dist/use-upload-C7QZSt1M.mjs.map +1 -0
- package/dist/use-upload-metrics-DEaujDeM.mjs +2 -0
- package/dist/use-upload-metrics-DEaujDeM.mjs.map +1 -0
- package/dist/{use-upload-metrics-Vho0Lzmq.d.mts → use-upload-metrics-R1xNz6Aa.d.mts} +5 -5
- package/dist/use-upload-metrics-R1xNz6Aa.d.mts.map +1 -0
- package/dist/{use-uploadista-client-CRUhyWoy.d.mts → use-uploadista-client-ty1ffKD7.d.mts} +16 -13
- package/dist/use-uploadista-client-ty1ffKD7.d.mts.map +1 -0
- package/package.json +5 -5
- package/src/contexts/flow-manager-context.tsx +22 -35
- package/src/hooks/use-flow-upload.ts +45 -30
- package/src/hooks/use-multi-flow-upload.ts +7 -3
- package/src/hooks/use-upload-events.ts +43 -21
- package/src/hooks/use-uploadista-events.ts +1 -1
- package/dist/use-upload-DSYzF2Et.mjs +0 -2
- package/dist/use-upload-DSYzF2Et.mjs.map +0 -1
- package/dist/use-upload-metrics-DFVcWvCk.mjs +0 -2
- package/dist/use-upload-metrics-DFVcWvCk.mjs.map +0 -1
- package/dist/use-upload-metrics-Vho0Lzmq.d.mts.map +0 -1
- package/dist/use-uploadista-client-CRUhyWoy.d.mts.map +0 -1
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
BrowserUploadInput,
|
|
3
|
+
FlowUploadOptions,
|
|
4
|
+
UploadistaEvent,
|
|
5
|
+
} from "@uploadista/client-browser";
|
|
2
6
|
import {
|
|
3
7
|
FlowManager,
|
|
4
8
|
type FlowManagerCallbacks,
|
|
5
|
-
type FlowUploadState,
|
|
6
9
|
} from "@uploadista/client-core";
|
|
7
10
|
import { EventType, type FlowEvent } from "@uploadista/core/flow";
|
|
8
11
|
import { UploadEventType } from "@uploadista/core/types";
|
|
@@ -15,7 +18,6 @@ import {
|
|
|
15
18
|
useRef,
|
|
16
19
|
} from "react";
|
|
17
20
|
import { useUploadistaContext } from "../components/uploadista-provider";
|
|
18
|
-
import type { FlowUploadOptions } from "@uploadista/client-browser";
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* Type guard to check if an event is a flow event
|
|
@@ -37,8 +39,8 @@ function isFlowEvent(event: UploadistaEvent): event is FlowEvent {
|
|
|
37
39
|
/**
|
|
38
40
|
* Internal manager registry entry with ref counting
|
|
39
41
|
*/
|
|
40
|
-
interface ManagerEntry
|
|
41
|
-
manager: FlowManager<unknown
|
|
42
|
+
interface ManagerEntry {
|
|
43
|
+
manager: FlowManager<unknown>;
|
|
42
44
|
refCount: number;
|
|
43
45
|
flowId: string;
|
|
44
46
|
}
|
|
@@ -56,11 +58,11 @@ interface FlowManagerContextValue {
|
|
|
56
58
|
* @param options - Flow configuration options
|
|
57
59
|
* @returns FlowManager instance
|
|
58
60
|
*/
|
|
59
|
-
getManager:
|
|
61
|
+
getManager: (
|
|
60
62
|
flowId: string,
|
|
61
|
-
callbacks: FlowManagerCallbacks
|
|
62
|
-
options: FlowUploadOptions
|
|
63
|
-
) => FlowManager<unknown
|
|
63
|
+
callbacks: FlowManagerCallbacks,
|
|
64
|
+
options: FlowUploadOptions,
|
|
65
|
+
) => FlowManager<unknown>;
|
|
64
66
|
|
|
65
67
|
/**
|
|
66
68
|
* Release a flow manager reference.
|
|
@@ -101,9 +103,7 @@ interface FlowManagerProviderProps {
|
|
|
101
103
|
*/
|
|
102
104
|
export function FlowManagerProvider({ children }: FlowManagerProviderProps) {
|
|
103
105
|
const { client, subscribeToEvents } = useUploadistaContext();
|
|
104
|
-
const managersRef = useRef(
|
|
105
|
-
new Map<string, ManagerEntry<unknown>>(),
|
|
106
|
-
);
|
|
106
|
+
const managersRef = useRef(new Map<string, ManagerEntry>());
|
|
107
107
|
|
|
108
108
|
// Subscribe to all events and route to appropriate managers
|
|
109
109
|
useEffect(() => {
|
|
@@ -122,15 +122,11 @@ export function FlowManagerProvider({ children }: FlowManagerProviderProps) {
|
|
|
122
122
|
event.type === UploadEventType.UPLOAD_PROGRESS &&
|
|
123
123
|
"data" in event
|
|
124
124
|
) {
|
|
125
|
-
const uploadEvent = event
|
|
126
|
-
type: UploadEventType;
|
|
127
|
-
uploadId: string;
|
|
128
|
-
data: { progress: number; total: number | null };
|
|
129
|
-
};
|
|
125
|
+
const uploadEvent = event;
|
|
130
126
|
|
|
131
127
|
for (const entry of managersRef.current.values()) {
|
|
132
128
|
entry.manager.handleUploadProgress(
|
|
133
|
-
uploadEvent.
|
|
129
|
+
uploadEvent.data.id,
|
|
134
130
|
uploadEvent.data.progress,
|
|
135
131
|
uploadEvent.data.total,
|
|
136
132
|
);
|
|
@@ -142,36 +138,27 @@ export function FlowManagerProvider({ children }: FlowManagerProviderProps) {
|
|
|
142
138
|
}, [subscribeToEvents]);
|
|
143
139
|
|
|
144
140
|
const getManager = useCallback(
|
|
145
|
-
|
|
141
|
+
(
|
|
146
142
|
flowId: string,
|
|
147
|
-
callbacks: FlowManagerCallbacks
|
|
148
|
-
options: FlowUploadOptions
|
|
149
|
-
): FlowManager<unknown
|
|
143
|
+
callbacks: FlowManagerCallbacks,
|
|
144
|
+
options: FlowUploadOptions,
|
|
145
|
+
): FlowManager<unknown> => {
|
|
150
146
|
const existing = managersRef.current.get(flowId);
|
|
151
147
|
|
|
152
148
|
if (existing) {
|
|
153
149
|
// Increment ref count for existing manager
|
|
154
150
|
existing.refCount++;
|
|
155
|
-
return existing.manager
|
|
151
|
+
return existing.manager;
|
|
156
152
|
}
|
|
157
153
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
input: unknown,
|
|
161
|
-
flowConfig: FlowUploadOptions<TOutput>["flowConfig"],
|
|
162
|
-
internalOptions: unknown,
|
|
163
|
-
) => {
|
|
164
|
-
return client.uploadWithFlow(input, flowConfig, internalOptions);
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
const manager = new FlowManager<unknown, TOutput>(
|
|
168
|
-
flowUploadFn,
|
|
154
|
+
const manager = new FlowManager<BrowserUploadInput>(
|
|
155
|
+
client.uploadWithFlow,
|
|
169
156
|
callbacks,
|
|
170
157
|
options,
|
|
171
158
|
);
|
|
172
159
|
|
|
173
160
|
managersRef.current.set(flowId, {
|
|
174
|
-
manager
|
|
161
|
+
manager,
|
|
175
162
|
refCount: 1,
|
|
176
163
|
flowId,
|
|
177
164
|
});
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type { FlowUploadOptions } from "@uploadista/client-browser";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import type {
|
|
3
|
+
FlowManager,
|
|
4
|
+
FlowUploadState,
|
|
5
|
+
FlowUploadStatus,
|
|
6
6
|
} from "@uploadista/client-core";
|
|
7
7
|
import type { TypedOutput } from "@uploadista/core/flow";
|
|
8
|
-
import type { UploadFile } from "@uploadista/core/types";
|
|
9
8
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
10
9
|
import { useFlowManagerContext } from "../contexts/flow-manager-context";
|
|
11
10
|
|
|
@@ -15,8 +14,6 @@ export type { FlowUploadState, FlowUploadStatus };
|
|
|
15
14
|
/**
|
|
16
15
|
* Return value from the useFlowUpload hook with upload control methods and state.
|
|
17
16
|
*
|
|
18
|
-
* @template TOutput - Type of the final output from the flow (defaults to UploadFile)
|
|
19
|
-
*
|
|
20
17
|
* @property state - Complete flow upload state with progress and outputs
|
|
21
18
|
* @property upload - Function to initiate file upload through the flow
|
|
22
19
|
* @property abort - Cancel the current upload and flow execution
|
|
@@ -26,11 +23,11 @@ export type { FlowUploadState, FlowUploadStatus };
|
|
|
26
23
|
* @property isUploadingFile - True only during file upload phase
|
|
27
24
|
* @property isProcessing - True only during flow processing phase
|
|
28
25
|
*/
|
|
29
|
-
export interface UseFlowUploadReturn
|
|
26
|
+
export interface UseFlowUploadReturn {
|
|
30
27
|
/**
|
|
31
28
|
* Current upload state
|
|
32
29
|
*/
|
|
33
|
-
state: FlowUploadState
|
|
30
|
+
state: FlowUploadState;
|
|
34
31
|
|
|
35
32
|
/**
|
|
36
33
|
* Upload a file through the flow
|
|
@@ -74,7 +71,6 @@ const initialState: FlowUploadState = {
|
|
|
74
71
|
bytesUploaded: 0,
|
|
75
72
|
totalBytes: null,
|
|
76
73
|
error: null,
|
|
77
|
-
result: null,
|
|
78
74
|
jobId: null,
|
|
79
75
|
flowStarted: false,
|
|
80
76
|
currentNodeName: null,
|
|
@@ -93,7 +89,6 @@ const initialState: FlowUploadState = {
|
|
|
93
89
|
* Must be used within FlowManagerProvider (which must be within UploadistaProvider).
|
|
94
90
|
* Flow events are automatically routed by the provider to the appropriate manager.
|
|
95
91
|
*
|
|
96
|
-
* @template TOutput - Type of the final result from the flow (defaults to UploadFile)
|
|
97
92
|
* @param options - Flow upload configuration including flow ID and event handlers
|
|
98
93
|
* @returns Flow upload state and control methods
|
|
99
94
|
*
|
|
@@ -105,14 +100,16 @@ const initialState: FlowUploadState = {
|
|
|
105
100
|
* flowConfig: {
|
|
106
101
|
* flowId: "image-optimization-flow",
|
|
107
102
|
* storageId: "s3-images",
|
|
108
|
-
* outputNodeId: "optimized-output", // Optional: specify which output to use
|
|
109
103
|
* },
|
|
110
|
-
* onSuccess: (
|
|
111
|
-
* console.log("
|
|
104
|
+
* onSuccess: (outputs) => {
|
|
105
|
+
* console.log("Flow outputs:", outputs);
|
|
106
|
+
* // Access all outputs from the flow
|
|
107
|
+
* for (const output of outputs) {
|
|
108
|
+
* console.log(`${output.nodeId}:`, output.data);
|
|
109
|
+
* }
|
|
112
110
|
* },
|
|
113
111
|
* onFlowComplete: (outputs) => {
|
|
114
112
|
* console.log("All flow outputs:", outputs);
|
|
115
|
-
* // outputs might include: { thumbnail: {...}, optimized: {...}, original: {...} }
|
|
116
113
|
* },
|
|
117
114
|
* onError: (error) => {
|
|
118
115
|
* console.error("Upload or processing failed:", error);
|
|
@@ -146,8 +143,12 @@ const initialState: FlowUploadState = {
|
|
|
146
143
|
* {flowUpload.state.status === "success" && (
|
|
147
144
|
* <div>
|
|
148
145
|
* <p>Upload complete!</p>
|
|
149
|
-
* {flowUpload.state.
|
|
150
|
-
* <
|
|
146
|
+
* {flowUpload.state.flowOutputs && (
|
|
147
|
+
* <div>
|
|
148
|
+
* {flowUpload.state.flowOutputs.map((output) => (
|
|
149
|
+
* <div key={output.nodeId}>{output.nodeId}: {JSON.stringify(output.data)}</div>
|
|
150
|
+
* ))}
|
|
151
|
+
* </div>
|
|
151
152
|
* )}
|
|
152
153
|
* </div>
|
|
153
154
|
* )}
|
|
@@ -170,14 +171,10 @@ const initialState: FlowUploadState = {
|
|
|
170
171
|
* @see {@link useMultiFlowUpload} for uploading multiple files through a flow
|
|
171
172
|
* @see {@link useUpload} for simple uploads without flow processing
|
|
172
173
|
*/
|
|
173
|
-
export function useFlowUpload
|
|
174
|
-
options: FlowUploadOptions<TOutput>,
|
|
175
|
-
): UseFlowUploadReturn<TOutput> {
|
|
174
|
+
export function useFlowUpload(options: FlowUploadOptions): UseFlowUploadReturn {
|
|
176
175
|
const { getManager, releaseManager } = useFlowManagerContext();
|
|
177
|
-
const [state, setState] = useState<FlowUploadState
|
|
178
|
-
|
|
179
|
-
);
|
|
180
|
-
const managerRef = useRef<FlowManager<unknown, TOutput> | null>(null);
|
|
176
|
+
const [state, setState] = useState<FlowUploadState>(initialState);
|
|
177
|
+
const managerRef = useRef<FlowManager<unknown> | null>(null);
|
|
181
178
|
|
|
182
179
|
// Store callbacks in refs so they can be updated without recreating the manager
|
|
183
180
|
const callbacksRef = useRef(options);
|
|
@@ -195,17 +192,29 @@ export function useFlowUpload<TOutput = UploadFile>(
|
|
|
195
192
|
// Create stable callback wrappers that call the latest callbacks via refs
|
|
196
193
|
const stableCallbacks = {
|
|
197
194
|
onStateChange: setState,
|
|
198
|
-
onProgress: (
|
|
195
|
+
onProgress: (
|
|
196
|
+
uploadId: string,
|
|
197
|
+
bytesUploaded: number,
|
|
198
|
+
totalBytes: number | null,
|
|
199
|
+
) => {
|
|
199
200
|
callbacksRef.current.onProgress?.(uploadId, bytesUploaded, totalBytes);
|
|
200
201
|
},
|
|
201
|
-
onChunkComplete: (
|
|
202
|
-
|
|
202
|
+
onChunkComplete: (
|
|
203
|
+
chunkSize: number,
|
|
204
|
+
bytesAccepted: number,
|
|
205
|
+
bytesTotal: number | null,
|
|
206
|
+
) => {
|
|
207
|
+
callbacksRef.current.onChunkComplete?.(
|
|
208
|
+
chunkSize,
|
|
209
|
+
bytesAccepted,
|
|
210
|
+
bytesTotal,
|
|
211
|
+
);
|
|
203
212
|
},
|
|
204
213
|
onFlowComplete: (outputs: TypedOutput[]) => {
|
|
205
214
|
callbacksRef.current.onFlowComplete?.(outputs);
|
|
206
215
|
},
|
|
207
|
-
onSuccess: (
|
|
208
|
-
callbacksRef.current.onSuccess?.(
|
|
216
|
+
onSuccess: (outputs: TypedOutput[]) => {
|
|
217
|
+
callbacksRef.current.onSuccess?.(outputs);
|
|
209
218
|
},
|
|
210
219
|
onError: (error: Error) => {
|
|
211
220
|
callbacksRef.current.onError?.(error);
|
|
@@ -223,7 +232,13 @@ export function useFlowUpload<TOutput = UploadFile>(
|
|
|
223
232
|
releaseManager(flowId);
|
|
224
233
|
managerRef.current = null;
|
|
225
234
|
};
|
|
226
|
-
}, [
|
|
235
|
+
}, [
|
|
236
|
+
options.flowConfig.flowId,
|
|
237
|
+
options.flowConfig.storageId,
|
|
238
|
+
options.flowConfig.outputNodeId,
|
|
239
|
+
getManager,
|
|
240
|
+
releaseManager,
|
|
241
|
+
]);
|
|
227
242
|
|
|
228
243
|
// Wrap manager methods with useCallback
|
|
229
244
|
const upload = useCallback(async (file: File | Blob) => {
|
|
@@ -4,7 +4,6 @@ import type {
|
|
|
4
4
|
MultiFlowUploadOptions,
|
|
5
5
|
MultiFlowUploadState,
|
|
6
6
|
} from "@uploadista/client-browser";
|
|
7
|
-
import type { UploadFile } from "@uploadista/core/types";
|
|
8
7
|
import { useCallback, useRef, useState } from "react";
|
|
9
8
|
import { useUploadistaContext } from "../components/uploadista-provider";
|
|
10
9
|
|
|
@@ -271,11 +270,16 @@ export function useMultiFlowUpload(
|
|
|
271
270
|
return updated;
|
|
272
271
|
});
|
|
273
272
|
},
|
|
274
|
-
onSuccess: (
|
|
273
|
+
onSuccess: (outputs) => {
|
|
275
274
|
setItems((prev) => {
|
|
276
275
|
const updated = prev.map((i) =>
|
|
277
276
|
i.id === itemId
|
|
278
|
-
? {
|
|
277
|
+
? {
|
|
278
|
+
...i,
|
|
279
|
+
status: "success" as const,
|
|
280
|
+
result: outputs,
|
|
281
|
+
progress: 100,
|
|
282
|
+
}
|
|
279
283
|
: i,
|
|
280
284
|
);
|
|
281
285
|
const updatedItem = updated.find((i) => i.id === itemId);
|
|
@@ -151,41 +151,63 @@ export function useUploadEvents(options: UseUploadEventsOptions): void {
|
|
|
151
151
|
if (!isUploadEvent(event)) return;
|
|
152
152
|
|
|
153
153
|
// Route to appropriate callback based on event type
|
|
154
|
+
// Note: flow context is at the top level of the event, not inside data
|
|
155
|
+
const flowContext = "flow" in event ? event.flow : undefined;
|
|
156
|
+
|
|
154
157
|
switch (event.type) {
|
|
155
158
|
case UploadEventType.UPLOAD_STARTED:
|
|
156
|
-
options.onUploadStarted?.(
|
|
157
|
-
event.data as unknown as UploadFileEventData,
|
|
158
|
-
|
|
159
|
+
options.onUploadStarted?.({
|
|
160
|
+
...(event.data as unknown as Omit<UploadFileEventData, "flow">),
|
|
161
|
+
flow: flowContext,
|
|
162
|
+
});
|
|
159
163
|
break;
|
|
160
164
|
case UploadEventType.UPLOAD_PROGRESS:
|
|
161
|
-
options.onUploadProgress?.(
|
|
162
|
-
event.data as unknown as
|
|
163
|
-
|
|
165
|
+
options.onUploadProgress?.({
|
|
166
|
+
...(event.data as unknown as Omit<
|
|
167
|
+
UploadProgressEventData,
|
|
168
|
+
"flow"
|
|
169
|
+
>),
|
|
170
|
+
flow: flowContext,
|
|
171
|
+
});
|
|
164
172
|
break;
|
|
165
173
|
case UploadEventType.UPLOAD_COMPLETE:
|
|
166
|
-
options.onUploadComplete?.(
|
|
167
|
-
event.data as unknown as UploadFileEventData,
|
|
168
|
-
|
|
174
|
+
options.onUploadComplete?.({
|
|
175
|
+
...(event.data as unknown as Omit<UploadFileEventData, "flow">),
|
|
176
|
+
flow: flowContext,
|
|
177
|
+
});
|
|
169
178
|
break;
|
|
170
179
|
case UploadEventType.UPLOAD_FAILED:
|
|
171
|
-
options.onUploadFailed?.(
|
|
172
|
-
event.data as unknown as UploadFailedEventData,
|
|
173
|
-
|
|
180
|
+
options.onUploadFailed?.({
|
|
181
|
+
...(event.data as unknown as Omit<UploadFailedEventData, "flow">),
|
|
182
|
+
flow: flowContext,
|
|
183
|
+
});
|
|
174
184
|
break;
|
|
175
185
|
case UploadEventType.UPLOAD_VALIDATION_SUCCESS:
|
|
176
|
-
options.onUploadValidationSuccess?.(
|
|
177
|
-
event.data as unknown as
|
|
178
|
-
|
|
186
|
+
options.onUploadValidationSuccess?.({
|
|
187
|
+
...(event.data as unknown as Omit<
|
|
188
|
+
UploadValidationSuccessEventData,
|
|
189
|
+
"flow"
|
|
190
|
+
>),
|
|
191
|
+
flow: flowContext,
|
|
192
|
+
});
|
|
179
193
|
break;
|
|
180
194
|
case UploadEventType.UPLOAD_VALIDATION_FAILED:
|
|
181
|
-
options.onUploadValidationFailed?.(
|
|
182
|
-
event.data as unknown as
|
|
183
|
-
|
|
195
|
+
options.onUploadValidationFailed?.({
|
|
196
|
+
...(event.data as unknown as Omit<
|
|
197
|
+
UploadValidationFailedEventData,
|
|
198
|
+
"flow"
|
|
199
|
+
>),
|
|
200
|
+
flow: flowContext,
|
|
201
|
+
});
|
|
184
202
|
break;
|
|
185
203
|
case UploadEventType.UPLOAD_VALIDATION_WARNING:
|
|
186
|
-
options.onUploadValidationWarning?.(
|
|
187
|
-
event.data as unknown as
|
|
188
|
-
|
|
204
|
+
options.onUploadValidationWarning?.({
|
|
205
|
+
...(event.data as unknown as Omit<
|
|
206
|
+
UploadValidationWarningEventData,
|
|
207
|
+
"flow"
|
|
208
|
+
>),
|
|
209
|
+
flow: flowContext,
|
|
210
|
+
});
|
|
189
211
|
break;
|
|
190
212
|
}
|
|
191
213
|
});
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{EventType as e}from"@uploadista/core/flow";import{UploadEventType as t}from"@uploadista/core/types";import{createContext as n,useCallback as r,useContext as i,useEffect as a,useMemo as o,useRef as s,useState as c}from"react";import{FlowManager as l,UploadManager as u}from"@uploadista/client-core";import{jsx as d}from"react/jsx-runtime";import{createUploadistaClient as f}from"@uploadista/client-browser";function p(t){let n=t;return n.eventType===e.FlowStart||n.eventType===e.FlowEnd||n.eventType===e.FlowError||n.eventType===e.NodeStart||n.eventType===e.NodeEnd||n.eventType===e.NodePause||n.eventType===e.NodeResume||n.eventType===e.NodeError}const m=n(void 0);function h({children:e}){let{client:n,subscribeToEvents:i}=b(),o=s(new Map);a(()=>i(e=>{if(p(e)){for(let t of o.current.values())t.manager.handleFlowEvent(e);return}if(`type`in e&&e.type===t.UPLOAD_PROGRESS&&`data`in e){let t=e;for(let e of o.current.values())e.manager.handleUploadProgress(t.uploadId,t.data.progress,t.data.total)}}),[i]);let c=r((e,t,r)=>{let i=o.current.get(e);if(i)return i.refCount++,i.manager;let a=new l((e,t,r)=>n.uploadWithFlow(e,t,r),t,r);return o.current.set(e,{manager:a,refCount:1,flowId:e}),a},[n]),u=r(e=>{let t=o.current.get(e);t&&(t.refCount--,t.refCount<=0&&(t.manager.cleanup(),o.current.delete(e)))},[]);return d(m.Provider,{value:{getManager:c,releaseManager:u},children:e})}function g(){let e=i(m);if(e===void 0)throw Error(`useFlowManagerContext must be used within a FlowManagerProvider. Make sure to wrap your component tree with <FlowManagerProvider>.`);return e}function _(e){let t=s(e);return t.current=e,{client:o(()=>(console.log(`[useUploadistaClient] Creating NEW client instance with onEvent:`,e.onEvent),f({baseUrl:e.baseUrl,storageId:e.storageId,uploadistaBasePath:e.uploadistaBasePath,chunkSize:e.chunkSize,storeFingerprintForResuming:e.storeFingerprintForResuming,retryDelays:e.retryDelays,parallelUploads:e.parallelUploads,parallelChunkSize:e.parallelChunkSize,uploadStrategy:e.uploadStrategy,smartChunking:e.smartChunking,networkMonitoring:e.networkMonitoring,uploadMetrics:e.uploadMetrics,connectionPooling:e.connectionPooling,auth:e.auth,onEvent:e.onEvent})),[e.baseUrl,e.storageId,e.uploadistaBasePath,e.chunkSize,e.storeFingerprintForResuming,e.retryDelays,e.parallelUploads,e.parallelChunkSize,e.uploadStrategy,e.smartChunking,e.networkMonitoring,e.uploadMetrics,e.connectionPooling,e.auth,e.onEvent]),config:e}}const v=n(null);function y({children:e,...t}){let n=s(new Set),i=r(e=>{n.current.forEach(t=>{try{t(e)}catch(e){console.error(`Error in event subscriber:`,e)}})},[]),a=_({...t,onEvent:i}),c=r(e=>(n.current.add(e),()=>{n.current.delete(e)}),[]),l=o(()=>({...a,subscribeToEvents:c}),[a,c]);return d(v.Provider,{value:l,children:d(h,{children:e})})}function b(){let e=i(v);if(e===null)throw Error(`useUploadistaContext must be used within an UploadistaProvider. Make sure to wrap your component tree with <UploadistaProvider>.`);return e}function x(e){let t=b(),[n,i]=c([]),a=s(new Map),o=s([]),l=s(0),u=e.maxConcurrent??3,d=r(e=>{if(e.length===0)return 0;let t=e.reduce((e,t)=>e+t.progress,0);return Math.round(t/e.length)},[]),f=r(async()=>{if(l.current>=u||o.current.length===0)return;let r=o.current.shift();if(!r)return;let s=n.find(e=>e.id===r);if(!s||s.status!==`pending`){f();return}l.current++,i(e=>e.map(e=>e.id===r?{...e,status:`uploading`}:e));try{let{abort:n,jobId:o}=await t.client.uploadWithFlow(s.file,e.flowConfig,{onJobStart:e=>{i(t=>t.map(t=>t.id===r?{...t,jobId:e}:t))},onProgress:(t,n,a)=>{let o=a?Math.round(n/a*100):0;i(t=>{let i=t.map(e=>e.id===r?{...e,progress:o,bytesUploaded:n,totalBytes:a||0}:e),s=i.find(e=>e.id===r);return s&&e.onItemProgress?.(s),i})},onSuccess:t=>{i(n=>{let i=n.map(e=>e.id===r?{...e,status:`success`,result:t,progress:100}:e),a=i.find(e=>e.id===r);return a&&e.onItemSuccess?.(a),i.every(e=>e.status===`success`||e.status===`error`||e.status===`aborted`)&&e.onComplete?.(i),i}),a.current.delete(r),l.current--,f()},onError:t=>{i(n=>{let i=n.map(e=>e.id===r?{...e,status:`error`,error:t}:e),a=i.find(e=>e.id===r);return a&&e.onItemError?.(a,t),i.every(e=>e.status===`success`||e.status===`error`||e.status===`aborted`)&&e.onComplete?.(i),i}),a.current.delete(r),l.current--,f()},onShouldRetry:e.onShouldRetry});a.current.set(r,n),i(e=>e.map(e=>e.id===r?{...e,jobId:o}:e))}catch(e){i(t=>t.map(t=>t.id===r?{...t,status:`error`,error:e}:t)),l.current--,f()}},[t,n,u,e]),p=r(e=>{let t=Array.from(e).map(e=>({id:`${Date.now()}-${Math.random().toString(36).substr(2,9)}`,file:e,status:`pending`,progress:0,bytesUploaded:0,totalBytes:e.size,error:null,result:null,jobId:null}));i(e=>[...e,...t])},[]),m=r(e=>{let t=a.current.get(e);t&&(t(),a.current.delete(e)),i(t=>t.filter(t=>t.id!==e)),o.current=o.current.filter(t=>t!==e)},[]),h=r(()=>{let e=n.filter(e=>e.status===`pending`);o.current.push(...e.map(e=>e.id));for(let e=0;e<u;e++)f()},[n,u,f]),g=r(e=>{let t=a.current.get(e);t&&(t(),a.current.delete(e),i(t=>t.map(t=>t.id===e?{...t,status:`aborted`}:t)),l.current--,f())},[f]),_=r(()=>{for(let e of a.current.values())e();a.current.clear(),o.current=[],l.current=0,i(e=>e.map(e=>e.status===`uploading`?{...e,status:`aborted`}:e))},[]),v=r(()=>{_(),i([])},[_]),y=r(e=>{i(t=>t.map(t=>t.id===e?{...t,status:`pending`,progress:0,bytesUploaded:0,error:null}:t)),o.current.push(e),f()},[f]),x={items:n,totalProgress:d(n),activeUploads:n.filter(e=>e.status===`uploading`).length,completedUploads:n.filter(e=>e.status===`success`).length,failedUploads:n.filter(e=>e.status===`error`).length};return{state:x,addFiles:p,removeFile:m,startUpload:h,abortUpload:g,abortAll:_,clear:v,retryUpload:y,isUploading:x.activeUploads>0}}const S={isDragging:!1,isOver:!1,isValid:!0,errors:[]};function C(e={}){let{accept:t,maxFiles:n,maxFileSize:i,multiple:a=!0,validator:o,onFilesReceived:l,onValidationError:u,onDragStateChange:d}=e,[f,p]=c(S),m=s(null),h=s(0),g=r(e=>{p(t=>({...t,...e}))},[]),_=r(e=>{let r=[];n&&e.length>n&&r.push(`Maximum ${n} files allowed. You selected ${e.length} files.`);for(let n of e){if(i&&n.size>i){let e=(i/(1024*1024)).toFixed(1),t=(n.size/(1024*1024)).toFixed(1);r.push(`File "${n.name}" (${t}MB) exceeds maximum size of ${e}MB.`)}t&&t.length>0&&(t.some(e=>{if(e.startsWith(`.`))return n.name.toLowerCase().endsWith(e.toLowerCase());if(e.endsWith(`/*`)){let t=e.slice(0,-2);return n.type.startsWith(t)}else return n.type===e})||r.push(`File "${n.name}" type "${n.type}" is not accepted. Accepted types: ${t.join(`, `)}.`))}if(o){let t=o(e);t&&r.push(...t)}return r},[t,n,i,o]),v=r(e=>{let t=Array.from(e),n=_(t);n.length>0?(g({errors:n,isValid:!1}),u?.(n)):(g({errors:[],isValid:!0}),l?.(t))},[_,g,l,u]),y=r(e=>{let t=[];if(e.items)for(let n=0;n<e.items.length;n++){let r=e.items[n];if(r&&r.kind===`file`){let e=r.getAsFile();e&&t.push(e)}}else for(let n=0;n<e.files.length;n++){let r=e.files[n];r&&t.push(r)}return t},[]),b=r(e=>{e.preventDefault(),e.stopPropagation(),h.current++,h.current===1&&(g({isDragging:!0,isOver:!0}),d?.(!0))},[g,d]),x=r(e=>{e.preventDefault(),e.stopPropagation(),e.dataTransfer&&(e.dataTransfer.dropEffect=`copy`)},[]),C=r(e=>{e.preventDefault(),e.stopPropagation(),h.current--,h.current===0&&(g({isDragging:!1,isOver:!1,errors:[]}),d?.(!1))},[g,d]),w=r(e=>{if(e.preventDefault(),e.stopPropagation(),h.current=0,g({isDragging:!1,isOver:!1}),d?.(!1),e.dataTransfer){let t=y(e.dataTransfer);t.length>0&&v(t)}},[g,d,y,v]),T=r(()=>{m.current?.click()},[]),E=r(e=>{e.target.files&&e.target.files.length>0&&v(Array.from(e.target.files)),e.target.value=``},[v]),D=r(()=>{p(S),h.current=0},[]);return{state:f,dragHandlers:{onDragEnter:b,onDragOver:x,onDragLeave:C,onDrop:w},inputProps:{type:`file`,multiple:a,accept:t?.join(`, `),onChange:E,style:{display:`none`},ref:m},openFilePicker:T,processFiles:v,reset:D}}const w={status:`idle`,progress:0,bytesUploaded:0,totalBytes:null,error:null,result:null,jobId:null,flowStarted:!1,currentNodeName:null,currentNodeType:null,flowOutputs:null};function T(e){let{getManager:t,releaseManager:n}=g(),[i,o]=c(w),l=s(null),u=s(e);return a(()=>{u.current=e}),a(()=>{let r=e.flowConfig.flowId;return l.current=t(r,{onStateChange:o,onProgress:(e,t,n)=>{u.current.onProgress?.(e,t,n)},onChunkComplete:(e,t,n)=>{u.current.onChunkComplete?.(e,t,n)},onFlowComplete:e=>{u.current.onFlowComplete?.(e)},onSuccess:e=>{u.current.onSuccess?.(e)},onError:e=>{u.current.onError?.(e)},onAbort:()=>{u.current.onAbort?.()}},e),()=>{n(r),l.current=null}},[e.flowConfig.flowId,e.flowConfig.storageId,e.flowConfig.outputNodeId,t,n]),{state:i,upload:r(async e=>{await l.current?.upload(e)},[]),abort:r(()=>{l.current?.abort()},[]),pause:r(()=>{l.current?.pause()},[]),reset:r(()=>{l.current?.reset()},[]),isUploading:i.status===`uploading`||i.status===`processing`,isUploadingFile:i.status===`uploading`,isProcessing:i.status===`processing`}}function E(e={}){let t=b(),{maxConcurrent:n=3}=e,[i,a]=c([]),o=s([]),l=s(0),u=s(new Set),d=s(new Map);o.current=i;let f=r(()=>`upload-${Date.now()}-${l.current++}`,[]),p=r((e,t)=>{a(n=>{let r=n.map(n=>n.id===e?{...n,state:{...n.state,...t}}:n);return o.current=r,r})},[]),m=r(()=>{let t=o.current;if(t.every(e=>[`success`,`error`,`aborted`].includes(e.state.status))&&t.length>0){let n=t.filter(e=>e.state.status===`success`),r=t.filter(e=>[`error`,`aborted`].includes(e.state.status));e.onComplete?.({successful:n,failed:r,total:t.length})}},[e]),h=r(()=>{if(u.current.size>=n)return;let r=o.current.find(e=>e.state.status===`idle`&&!u.current.has(e.id));r&&(async()=>{u.current.add(r.id),e.onUploadStart?.(r),p(r.id,{status:`uploading`});try{let n=await t.client.upload(r.file,{metadata:e.metadata,uploadLengthDeferred:e.uploadLengthDeferred,uploadSize:e.uploadSize,onProgress:(t,n,i)=>{let a=i?Math.round(n/i*100):0;p(r.id,{progress:a,bytesUploaded:n,totalBytes:i}),e.onUploadProgress?.(r,a,n,i)},onChunkComplete:()=>{},onSuccess:t=>{p(r.id,{status:`success`,result:t,progress:100});let n={...r,state:{...r.state,status:`success`,result:t}};e.onUploadSuccess?.(n,t),u.current.delete(r.id),d.current.delete(r.id),h(),m()},onError:t=>{p(r.id,{status:`error`,error:t});let n={...r,state:{...r.state,status:`error`,error:t}};e.onUploadError?.(n,t),u.current.delete(r.id),d.current.delete(r.id),h(),m()},onShouldRetry:e.onShouldRetry});d.current.set(r.id,n)}catch(t){p(r.id,{status:`error`,error:t});let n={...r,state:{...r.state,status:`error`,error:t}};e.onUploadError?.(n,t),u.current.delete(r.id),d.current.delete(r.id),h(),m()}})()},[n,t,e,p,m]),g={total:i.length,completed:i.filter(e=>[`success`,`error`,`aborted`].includes(e.state.status)).length,successful:i.filter(e=>e.state.status===`success`).length,failed:i.filter(e=>[`error`,`aborted`].includes(e.state.status)).length,uploading:i.filter(e=>e.state.status===`uploading`).length,progress:i.length>0?Math.round(i.reduce((e,t)=>e+t.state.progress,0)/i.length):0,totalBytesUploaded:i.reduce((e,t)=>e+t.state.bytesUploaded,0),totalBytes:i.reduce((e,t)=>e+(t.state.totalBytes||0),0),isUploading:i.some(e=>e.state.status===`uploading`),isComplete:i.length>0&&i.every(e=>[`success`,`error`,`aborted`].includes(e.state.status))},_=r(e=>{let t=e.map(e=>({id:f(),file:e,state:{status:`idle`,progress:0,bytesUploaded:0,totalBytes:e instanceof File?e.size:null,error:null,result:null}}));console.log(`addFiles: Adding`,t.length,`files`);let n=[...o.current,...t];o.current=n,console.log(`addFiles: Updated itemsRef.current to`,n.length,`items`),a(n)},[f]),v=r(e=>{let t=o.current.find(t=>t.id===e);if(t&&t.state.status===`uploading`){let t=d.current.get(e);t&&(t.abort(),d.current.delete(e))}a(t=>{let n=t.filter(t=>t.id!==e);return o.current=n,n}),u.current.delete(e)},[]),y=r(e=>{let t=o.current.find(t=>t.id===e);if(t&&t.state.status===`uploading`){let t=d.current.get(e);t&&(t.abort(),d.current.delete(e)),u.current.delete(e),a(t=>{let n=t.map(t=>t.id===e?{...t,state:{...t.state,status:`aborted`}}:t);return o.current=n,n}),h()}},[h]),x=r(e=>{let t=o.current.find(t=>t.id===e);t&&[`error`,`aborted`].includes(t.state.status)&&(a(t=>{let n=t.map(t=>t.id===e?{...t,state:{...t.state,status:`idle`,error:null}}:t);return o.current=n,n}),setTimeout(()=>h(),0))},[h]),S=r(()=>{let e=o.current;console.log(`Starting all uploads`,e);let t=e.filter(e=>e.state.status===`idle`),r=n-u.current.size,i=t.slice(0,r);for(let e of i)console.log(`Starting next upload`,e),h()},[n,h]),C=r(()=>{o.current.filter(e=>e.state.status===`uploading`).forEach(e=>{let t=d.current.get(e.id);t&&(t.abort(),d.current.delete(e.id))}),u.current.clear(),a(e=>{let t=e.map(e=>e.state.status===`uploading`?{...e,state:{...e.state,status:`aborted`}}:e);return o.current=t,t})},[]);return{state:g,items:i,addFiles:_,removeItem:v,removeFile:v,startAll:S,abortUpload:y,abortAll:C,retryUpload:x,retryFailed:r(()=>{let e=o.current.filter(e=>[`error`,`aborted`].includes(e.state.status));e.length>0&&(a(t=>{let n=t.map(t=>e.some(e=>e.id===t.id)?{...t,state:{...t.state,status:`idle`,error:null}}:t);return o.current=n,n}),setTimeout(S,0))},[S]),clearCompleted:r(()=>{a(e=>{let t=e.filter(e=>![`success`,`error`,`aborted`].includes(e.state.status));return o.current=t,t})},[]),clearAll:r(()=>{C(),a([]),o.current=[],u.current.clear()},[C]),getItemsByStatus:r(e=>o.current.filter(t=>t.state.status===e),[]),metrics:{getInsights:()=>t.client.getChunkingInsights(),exportMetrics:()=>t.client.exportMetrics(),getNetworkMetrics:()=>t.client.getNetworkMetrics(),getNetworkCondition:()=>t.client.getNetworkCondition(),resetMetrics:()=>t.client.resetMetrics()}}}const D={status:`idle`,progress:0,bytesUploaded:0,totalBytes:null,error:null,result:null};function O(e={}){let t=b(),[n,i]=c(D),o=s(null);return a(()=>(o.current=new u((e,n)=>t.client.upload(e,n),{onStateChange:i,onProgress:e.onProgress,onChunkComplete:e.onChunkComplete,onSuccess:e.onSuccess,onError:e.onError,onAbort:e.onAbort},{metadata:e.metadata,uploadLengthDeferred:e.uploadLengthDeferred,uploadSize:e.uploadSize,onShouldRetry:e.onShouldRetry}),()=>{o.current?.cleanup()}),[t,e]),{state:n,upload:r(e=>{o.current?.upload(e)},[]),abort:r(()=>{o.current?.abort()},[]),reset:r(()=>{o.current?.reset()},[]),retry:r(()=>{o.current?.retry()},[]),isUploading:n.status===`uploading`,canRetry:o.current?.canRetry()??!1,metrics:{getInsights:()=>t.client.getChunkingInsights(),exportMetrics:()=>t.client.exportMetrics(),getNetworkMetrics:()=>t.client.getNetworkMetrics(),getNetworkCondition:()=>t.client.getNetworkCondition(),resetMetrics:()=>t.client.resetMetrics()}}}export{x as a,_ as c,C as i,h as l,E as n,y as o,T as r,b as s,O as t,g as u};
|
|
2
|
-
//# sourceMappingURL=use-upload-DSYzF2Et.mjs.map
|