pinata 2.4.6 → 2.4.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.
@@ -1 +1,21 @@
1
- export { s as AuthenticationError, N as NetworkError, r as PinataError, R as ReactUploadOptions, x as UploadResult, y as UseUploadReturn, t as ValidationError, v as convert, w as useUpload } from '../index-CQFQEo3K.mjs';
1
+ import { i as UploadResponse, h as UploadOptions } from '../gateway-tools-l9hk7kz4.mjs';
2
+ export { s as AuthenticationError, N as NetworkError, r as PinataError, t as ValidationError, v as convert } from '../gateway-tools-l9hk7kz4.mjs';
3
+
4
+ type UploadResult = UploadResponse | string;
5
+ interface ReactUploadOptions extends UploadOptions {
6
+ chunkSize?: number;
7
+ }
8
+ type UseUploadReturn = {
9
+ progress: number;
10
+ loading: boolean;
11
+ error: Error | null;
12
+ uploadResponse: UploadResult | null;
13
+ upload: (file: File, network: "public" | "private", url: string, options?: UploadOptions) => Promise<void>;
14
+ pause: () => void;
15
+ resume: () => void;
16
+ cancel: () => void;
17
+ };
18
+
19
+ declare const useUpload: () => UseUploadReturn;
20
+
21
+ export { type ReactUploadOptions, type UploadResult, type UseUploadReturn, useUpload };
@@ -1 +1,21 @@
1
- export { s as AuthenticationError, N as NetworkError, r as PinataError, R as ReactUploadOptions, x as UploadResult, y as UseUploadReturn, t as ValidationError, v as convert, w as useUpload } from '../index-CQFQEo3K.js';
1
+ import { i as UploadResponse, h as UploadOptions } from '../gateway-tools-l9hk7kz4.js';
2
+ export { s as AuthenticationError, N as NetworkError, r as PinataError, t as ValidationError, v as convert } from '../gateway-tools-l9hk7kz4.js';
3
+
4
+ type UploadResult = UploadResponse | string;
5
+ interface ReactUploadOptions extends UploadOptions {
6
+ chunkSize?: number;
7
+ }
8
+ type UseUploadReturn = {
9
+ progress: number;
10
+ loading: boolean;
11
+ error: Error | null;
12
+ uploadResponse: UploadResult | null;
13
+ upload: (file: File, network: "public" | "private", url: string, options?: UploadOptions) => Promise<void>;
14
+ pause: () => void;
15
+ resume: () => void;
16
+ cancel: () => void;
17
+ };
18
+
19
+ declare const useUpload: () => UseUploadReturn;
20
+
21
+ export { type ReactUploadOptions, type UploadResult, type UseUploadReturn, useUpload };
@@ -1,32 +1,292 @@
1
1
  'use strict';
2
2
 
3
- var chunkP556VRQU_js = require('../chunk-P556VRQU.js');
4
-
3
+ var chunkBK3CLF3Z_js = require('../chunk-BK3CLF3Z.js');
4
+ var react = require('react');
5
5
 
6
+ var LARGE_FILE_THRESHOLD = 94371840;
7
+ var BASE_CHUNK_SIZE = 262144;
8
+ var DEFAULT_CHUNKS = 20 * 10;
9
+ var normalizeChunkSize = (size) => {
10
+ if (size < BASE_CHUNK_SIZE) {
11
+ return BASE_CHUNK_SIZE;
12
+ }
13
+ return Math.floor(size / BASE_CHUNK_SIZE) * BASE_CHUNK_SIZE;
14
+ };
15
+ var useUpload = () => {
16
+ const [progress, setProgress] = react.useState(0);
17
+ const [loading, setLoading] = react.useState(false);
18
+ const [error, setError] = react.useState(null);
19
+ const [uploadResponse, setUploadResponse] = react.useState(
20
+ null
21
+ );
22
+ const uploadUrlRef = react.useRef(null);
23
+ const pausedRef = react.useRef(false);
24
+ const cancelledRef = react.useRef(false);
25
+ const uploadOffsetRef = react.useRef(0);
26
+ const fileRef = react.useRef(null);
27
+ const headersRef = react.useRef({});
28
+ const lastResponseHeadersRef = react.useRef(null);
29
+ const chunkSizeRef = react.useRef(BASE_CHUNK_SIZE * DEFAULT_CHUNKS);
30
+ const resetState = react.useCallback(() => {
31
+ setProgress(0);
32
+ setError(null);
33
+ setUploadResponse(null);
34
+ uploadUrlRef.current = null;
35
+ pausedRef.current = false;
36
+ cancelledRef.current = false;
37
+ uploadOffsetRef.current = 0;
38
+ fileRef.current = null;
39
+ }, []);
40
+ const pause = react.useCallback(() => {
41
+ pausedRef.current = true;
42
+ }, []);
43
+ const resume = react.useCallback(() => {
44
+ if (pausedRef.current && uploadUrlRef.current && fileRef.current) {
45
+ pausedRef.current = false;
46
+ continueChunkedUpload();
47
+ }
48
+ }, []);
49
+ const cancel = react.useCallback(() => {
50
+ cancelledRef.current = true;
51
+ setLoading(false);
52
+ }, []);
53
+ const continueChunkedUpload = react.useCallback(async () => {
54
+ if (!uploadUrlRef.current || !fileRef.current) return;
55
+ try {
56
+ if (cancelledRef.current) {
57
+ resetState();
58
+ return;
59
+ }
60
+ if (pausedRef.current) return;
61
+ const file = fileRef.current;
62
+ const fileSize = file.size;
63
+ const offset = uploadOffsetRef.current;
64
+ const chunkSize = chunkSizeRef.current;
65
+ if (offset >= fileSize) {
66
+ await finalizeUpload();
67
+ return;
68
+ }
69
+ const endOffset = Math.min(offset + chunkSize, fileSize);
70
+ const chunk = file.slice(offset, endOffset);
71
+ const uploadReq = await fetch(uploadUrlRef.current, {
72
+ method: "PATCH",
73
+ headers: {
74
+ "Content-Type": "application/offset+octet-stream",
75
+ "Upload-Offset": offset.toString(),
76
+ ...headersRef.current
77
+ },
78
+ body: chunk
79
+ });
80
+ lastResponseHeadersRef.current = uploadReq.headers;
81
+ if (!uploadReq.ok) {
82
+ const errorData = await uploadReq.text();
83
+ throw new chunkBK3CLF3Z_js.NetworkError(
84
+ `HTTP error during chunk upload: ${errorData}`,
85
+ uploadReq.status,
86
+ {
87
+ error: errorData,
88
+ code: "HTTP_ERROR",
89
+ metadata: { requestUrl: uploadReq.url }
90
+ }
91
+ );
92
+ }
93
+ const newOffset = endOffset;
94
+ uploadOffsetRef.current = newOffset;
95
+ const newProgress = Math.min(newOffset / fileSize * 100, 99.9);
96
+ setProgress(newProgress);
97
+ continueChunkedUpload();
98
+ } catch (err) {
99
+ if (err instanceof Error) {
100
+ setError(err);
101
+ } else {
102
+ setError(new Error("Unknown error during upload"));
103
+ }
104
+ setLoading(false);
105
+ }
106
+ }, [resetState]);
107
+ const finalizeUpload = react.useCallback(async () => {
108
+ if (!uploadUrlRef.current || !fileRef.current) return;
109
+ try {
110
+ let cid = null;
111
+ if (lastResponseHeadersRef.current) {
112
+ cid = lastResponseHeadersRef.current.get("upload-cid");
113
+ }
114
+ setUploadResponse(cid);
115
+ setProgress(100);
116
+ setLoading(false);
117
+ } catch (err) {
118
+ if (err instanceof Error) {
119
+ setError(err);
120
+ } else {
121
+ setError(new Error("Unknown error during upload finalization"));
122
+ }
123
+ setLoading(false);
124
+ }
125
+ }, []);
126
+ const simpleUpload = async (file, network, url, options) => {
127
+ try {
128
+ const formData = new FormData();
129
+ formData.append("file", file, file.name);
130
+ formData.append("network", network);
131
+ formData.append("name", options?.metadata?.name || file.name);
132
+ if (options?.groupId) {
133
+ formData.append("group_id", options.groupId);
134
+ }
135
+ if (options?.metadata?.keyvalues) {
136
+ formData.append(
137
+ "keyvalues",
138
+ JSON.stringify(options.metadata.keyvalues)
139
+ );
140
+ }
141
+ if (options?.streamable) {
142
+ formData.append("streamable", "true");
143
+ }
144
+ const request = await fetch(url, {
145
+ method: "POST",
146
+ headers: headersRef.current,
147
+ body: formData
148
+ });
149
+ if (!request.ok) {
150
+ const errorData = await request.text();
151
+ if (request.status === 401 || request.status === 403) {
152
+ throw new chunkBK3CLF3Z_js.AuthenticationError(
153
+ `Authentication failed: ${errorData}`,
154
+ request.status,
155
+ {
156
+ error: errorData,
157
+ code: "AUTH_ERROR",
158
+ metadata: { requestUrl: request.url }
159
+ }
160
+ );
161
+ }
162
+ throw new chunkBK3CLF3Z_js.NetworkError(`HTTP error: ${errorData}`, request.status, {
163
+ error: errorData,
164
+ code: "HTTP_ERROR",
165
+ metadata: { requestUrl: request.url }
166
+ });
167
+ }
168
+ const res = await request.json();
169
+ setUploadResponse(res.data);
170
+ setProgress(100);
171
+ setLoading(false);
172
+ } catch (err) {
173
+ if (err instanceof Error) {
174
+ setError(err);
175
+ } else {
176
+ setError(new Error("Unknown error during upload"));
177
+ }
178
+ setLoading(false);
179
+ }
180
+ };
181
+ const upload = react.useCallback(
182
+ async (file, network, url, options) => {
183
+ try {
184
+ resetState();
185
+ setLoading(true);
186
+ fileRef.current = file;
187
+ const headers = { Source: "sdk/react" };
188
+ headersRef.current = headers;
189
+ if (options?.chunkSize && options.chunkSize > 0) {
190
+ chunkSizeRef.current = normalizeChunkSize(options.chunkSize);
191
+ } else {
192
+ chunkSizeRef.current = BASE_CHUNK_SIZE * DEFAULT_CHUNKS;
193
+ }
194
+ if (file.size <= LARGE_FILE_THRESHOLD) {
195
+ await simpleUpload(file, network, url, options);
196
+ return;
197
+ }
198
+ let metadata = `filename ${btoa(file.name)},filetype ${btoa(file.type)},network ${btoa(network)}`;
199
+ if (options?.groupId) {
200
+ metadata += `,group_id ${btoa(options.groupId)}`;
201
+ }
202
+ if (options?.metadata?.keyvalues) {
203
+ metadata += `,keyvalues ${btoa(JSON.stringify(options.metadata.keyvalues))}`;
204
+ }
205
+ if (options?.streamable) {
206
+ metadata += `,streamable ${btoa("true")}`;
207
+ }
208
+ const urlReq = await fetch(url, {
209
+ method: "POST",
210
+ headers: {
211
+ "Upload-Length": `${file.size}`,
212
+ "Upload-Metadata": metadata,
213
+ ...headers
214
+ }
215
+ });
216
+ if (!urlReq.ok) {
217
+ const errorData = await urlReq.text();
218
+ if (urlReq.status === 401 || urlReq.status === 403) {
219
+ throw new chunkBK3CLF3Z_js.AuthenticationError(
220
+ `Authentication failed: ${errorData}`,
221
+ urlReq.status,
222
+ {
223
+ error: errorData,
224
+ code: "AUTH_ERROR"
225
+ }
226
+ );
227
+ }
228
+ throw new chunkBK3CLF3Z_js.NetworkError("Error initializing upload", urlReq.status, {
229
+ error: errorData,
230
+ code: "HTTP_ERROR"
231
+ });
232
+ }
233
+ const uploadUrl = urlReq.headers.get("Location");
234
+ if (!uploadUrl) {
235
+ throw new chunkBK3CLF3Z_js.NetworkError("Upload URL not provided", urlReq.status, {
236
+ error: "No location header found",
237
+ code: "HTTP_ERROR"
238
+ });
239
+ }
240
+ uploadUrlRef.current = uploadUrl;
241
+ continueChunkedUpload();
242
+ } catch (err) {
243
+ if (err instanceof Error) {
244
+ setError(err);
245
+ } else {
246
+ setError(new Error("Unknown error during upload initialization"));
247
+ }
248
+ setLoading(false);
249
+ }
250
+ },
251
+ [resetState, continueChunkedUpload]
252
+ );
253
+ react.useEffect(() => {
254
+ return () => {
255
+ cancelledRef.current = true;
256
+ };
257
+ }, []);
258
+ return {
259
+ progress,
260
+ loading,
261
+ error,
262
+ uploadResponse,
263
+ upload,
264
+ pause,
265
+ resume,
266
+ cancel
267
+ };
268
+ };
6
269
 
7
270
  Object.defineProperty(exports, "AuthenticationError", {
8
271
  enumerable: true,
9
- get: function () { return chunkP556VRQU_js.AuthenticationError; }
272
+ get: function () { return chunkBK3CLF3Z_js.AuthenticationError; }
10
273
  });
11
274
  Object.defineProperty(exports, "NetworkError", {
12
275
  enumerable: true,
13
- get: function () { return chunkP556VRQU_js.NetworkError; }
276
+ get: function () { return chunkBK3CLF3Z_js.NetworkError; }
14
277
  });
15
278
  Object.defineProperty(exports, "PinataError", {
16
279
  enumerable: true,
17
- get: function () { return chunkP556VRQU_js.PinataError; }
280
+ get: function () { return chunkBK3CLF3Z_js.PinataError; }
18
281
  });
19
282
  Object.defineProperty(exports, "ValidationError", {
20
283
  enumerable: true,
21
- get: function () { return chunkP556VRQU_js.ValidationError; }
284
+ get: function () { return chunkBK3CLF3Z_js.ValidationError; }
22
285
  });
23
286
  Object.defineProperty(exports, "convert", {
24
287
  enumerable: true,
25
- get: function () { return chunkP556VRQU_js.convertToDesiredGateway; }
26
- });
27
- Object.defineProperty(exports, "useUpload", {
28
- enumerable: true,
29
- get: function () { return chunkP556VRQU_js.useUpload; }
288
+ get: function () { return chunkBK3CLF3Z_js.convertToDesiredGateway; }
30
289
  });
290
+ exports.useUpload = useUpload;
31
291
  //# sourceMappingURL=index.js.map
32
292
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
1
+ {"version":3,"sources":["../../src/react/hooks/useUpload.ts"],"names":["useState","useRef","useCallback","NetworkError","AuthenticationError","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["import { useState, useCallback, useRef, useEffect } from \"react\";\nimport {\n\tNetworkError,\n\tAuthenticationError,\n\ttype UseUploadReturn,\n\ttype UploadResult,\n\ttype ReactUploadOptions,\n} from \"../types\";\n\nconst LARGE_FILE_THRESHOLD = 94371840; // ~90MB\nconst BASE_CHUNK_SIZE = 262144; // 256KB\nconst DEFAULT_CHUNKS = 20 * 10;\n\nconst normalizeChunkSize = (size: number): number => {\n\tif (size < BASE_CHUNK_SIZE) {\n\t\treturn BASE_CHUNK_SIZE;\n\t}\n\treturn Math.floor(size / BASE_CHUNK_SIZE) * BASE_CHUNK_SIZE;\n};\n\nexport const useUpload = (): UseUploadReturn => {\n\tconst [progress, setProgress] = useState<number>(0);\n\tconst [loading, setLoading] = useState<boolean>(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst [uploadResponse, setUploadResponse] = useState<UploadResult | null>(\n\t\tnull,\n\t);\n\n\t// Refs for pause/resume/cancel\n\tconst uploadUrlRef = useRef<string | null>(null);\n\tconst pausedRef = useRef<boolean>(false);\n\tconst cancelledRef = useRef<boolean>(false);\n\tconst uploadOffsetRef = useRef<number>(0);\n\tconst fileRef = useRef<File | null>(null);\n\tconst headersRef = useRef<Record<string, string>>({});\n\tconst lastResponseHeadersRef = useRef<Headers | null>(null);\n\tconst chunkSizeRef = useRef<number>(BASE_CHUNK_SIZE * DEFAULT_CHUNKS);\n\n\tconst resetState = useCallback(() => {\n\t\tsetProgress(0);\n\t\tsetError(null);\n\t\tsetUploadResponse(null);\n\t\tuploadUrlRef.current = null;\n\t\tpausedRef.current = false;\n\t\tcancelledRef.current = false;\n\t\tuploadOffsetRef.current = 0;\n\t\tfileRef.current = null;\n\t}, []);\n\n\tconst pause = useCallback(() => {\n\t\tpausedRef.current = true;\n\t}, []);\n\n\tconst resume = useCallback(() => {\n\t\tif (pausedRef.current && uploadUrlRef.current && fileRef.current) {\n\t\t\tpausedRef.current = false;\n\t\t\tcontinueChunkedUpload();\n\t\t}\n\t}, []);\n\n\tconst cancel = useCallback(() => {\n\t\tcancelledRef.current = true;\n\t\tsetLoading(false);\n\t}, []);\n\n\t// Handle chunked upload for large files\n\tconst continueChunkedUpload = useCallback(async () => {\n\t\tif (!uploadUrlRef.current || !fileRef.current) return;\n\n\t\ttry {\n\t\t\tif (cancelledRef.current) {\n\t\t\t\tresetState();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (pausedRef.current) return;\n\n\t\t\tconst file = fileRef.current;\n\t\t\tconst fileSize = file.size;\n\t\t\tconst offset = uploadOffsetRef.current;\n\t\t\tconst chunkSize = chunkSizeRef.current;\n\n\t\t\tif (offset >= fileSize) {\n\t\t\t\t// Upload is complete\n\t\t\t\tawait finalizeUpload();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst endOffset = Math.min(offset + chunkSize, fileSize);\n\t\t\tconst chunk = file.slice(offset, endOffset);\n\n\t\t\t// Upload chunk\n\t\t\tconst uploadReq = await fetch(uploadUrlRef.current, {\n\t\t\t\tmethod: \"PATCH\",\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/offset+octet-stream\",\n\t\t\t\t\t\"Upload-Offset\": offset.toString(),\n\t\t\t\t\t...headersRef.current,\n\t\t\t\t},\n\t\t\t\tbody: chunk,\n\t\t\t});\n\n\t\t\tlastResponseHeadersRef.current = uploadReq.headers;\n\n\t\t\tif (!uploadReq.ok) {\n\t\t\t\tconst errorData = await uploadReq.text();\n\t\t\t\tthrow new NetworkError(\n\t\t\t\t\t`HTTP error during chunk upload: ${errorData}`,\n\t\t\t\t\tuploadReq.status,\n\t\t\t\t\t{\n\t\t\t\t\t\terror: errorData,\n\t\t\t\t\t\tcode: \"HTTP_ERROR\",\n\t\t\t\t\t\tmetadata: { requestUrl: uploadReq.url },\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Update offset and progress\n\t\t\tconst newOffset = endOffset;\n\t\t\tuploadOffsetRef.current = newOffset;\n\t\t\tconst newProgress = Math.min((newOffset / fileSize) * 100, 99.9);\n\t\t\tsetProgress(newProgress);\n\n\t\t\t// Continue with next chunk\n\t\t\tcontinueChunkedUpload();\n\t\t} catch (err) {\n\t\t\tif (err instanceof Error) {\n\t\t\t\tsetError(err);\n\t\t\t} else {\n\t\t\t\tsetError(new Error(\"Unknown error during upload\"));\n\t\t\t}\n\t\t\tsetLoading(false);\n\t\t}\n\t}, [resetState]);\n\n\t// Finalize upload and get response\n\tconst finalizeUpload = useCallback(async () => {\n\t\tif (!uploadUrlRef.current || !fileRef.current) return;\n\n\t\ttry {\n\t\t\t// Try to get CID from response headers\n\t\t\tlet cid = null;\n\t\t\tif (lastResponseHeadersRef.current) {\n\t\t\t\tcid = lastResponseHeadersRef.current.get(\"upload-cid\");\n\t\t\t}\n\n\t\t\t// If no CID in headers, we may need to fetch file info from the API\n\t\t\t// This would depend on your API's response format\n\n\t\t\tsetUploadResponse(cid);\n\t\t\tsetProgress(100);\n\t\t\tsetLoading(false);\n\t\t} catch (err) {\n\t\t\tif (err instanceof Error) {\n\t\t\t\tsetError(err);\n\t\t\t} else {\n\t\t\t\tsetError(new Error(\"Unknown error during upload finalization\"));\n\t\t\t}\n\t\t\tsetLoading(false);\n\t\t}\n\t}, []);\n\n\t// Direct upload for smaller files\n\tconst simpleUpload = async (\n\t\tfile: File,\n\t\tnetwork: \"public\" | \"private\",\n\t\turl: string,\n\t\toptions?: ReactUploadOptions,\n\t) => {\n\t\ttry {\n\t\t\tconst formData = new FormData();\n\t\t\tformData.append(\"file\", file, file.name);\n\t\t\tformData.append(\"network\", network);\n\t\t\tformData.append(\"name\", options?.metadata?.name || file.name);\n\n\t\t\tif (options?.groupId) {\n\t\t\t\tformData.append(\"group_id\", options.groupId);\n\t\t\t}\n\n\t\t\tif (options?.metadata?.keyvalues) {\n\t\t\t\tformData.append(\n\t\t\t\t\t\"keyvalues\",\n\t\t\t\t\tJSON.stringify(options.metadata.keyvalues),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (options?.streamable) {\n\t\t\t\tformData.append(\"streamable\", \"true\");\n\t\t\t}\n\n\t\t\tconst request = await fetch(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: headersRef.current,\n\t\t\t\tbody: formData,\n\t\t\t});\n\n\t\t\tif (!request.ok) {\n\t\t\t\tconst errorData = await request.text();\n\t\t\t\tif (request.status === 401 || request.status === 403) {\n\t\t\t\t\tthrow new AuthenticationError(\n\t\t\t\t\t\t`Authentication failed: ${errorData}`,\n\t\t\t\t\t\trequest.status,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\terror: errorData,\n\t\t\t\t\t\t\tcode: \"AUTH_ERROR\",\n\t\t\t\t\t\t\tmetadata: { requestUrl: request.url },\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthrow new NetworkError(`HTTP error: ${errorData}`, request.status, {\n\t\t\t\t\terror: errorData,\n\t\t\t\t\tcode: \"HTTP_ERROR\",\n\t\t\t\t\tmetadata: { requestUrl: request.url },\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst res = await request.json();\n\t\t\tsetUploadResponse(res.data);\n\t\t\tsetProgress(100);\n\t\t\tsetLoading(false);\n\t\t} catch (err) {\n\t\t\tif (err instanceof Error) {\n\t\t\t\tsetError(err);\n\t\t\t} else {\n\t\t\t\tsetError(new Error(\"Unknown error during upload\"));\n\t\t\t}\n\t\t\tsetLoading(false);\n\t\t}\n\t};\n\n\t// Main upload function\n\tconst upload = useCallback(\n\t\tasync (\n\t\t\tfile: File,\n\t\t\tnetwork: \"public\" | \"private\",\n\t\t\turl: string,\n\t\t\toptions?: ReactUploadOptions,\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tresetState();\n\t\t\t\tsetLoading(true);\n\t\t\t\tfileRef.current = file;\n\n\t\t\t\t// Set up headers\n\t\t\t\tconst headers: Record<string, string> = { Source: \"sdk/react\" };\n\t\t\t\theadersRef.current = headers;\n\n\t\t\t\tif (options?.chunkSize && options.chunkSize > 0) {\n\t\t\t\t\tchunkSizeRef.current = normalizeChunkSize(options.chunkSize);\n\t\t\t\t} else {\n\t\t\t\t\tchunkSizeRef.current = BASE_CHUNK_SIZE * DEFAULT_CHUNKS;\n\t\t\t\t}\n\n\t\t\t\t// For smaller files, use simple upload\n\t\t\t\tif (file.size <= LARGE_FILE_THRESHOLD) {\n\t\t\t\t\tawait simpleUpload(file, network, url, options);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// For larger files, use chunked upload with TUS protocol\n\t\t\t\tlet metadata = `filename ${btoa(file.name)},filetype ${btoa(file.type)},network ${btoa(network)}`;\n\n\t\t\t\tif (options?.groupId) {\n\t\t\t\t\tmetadata += `,group_id ${btoa(options.groupId)}`;\n\t\t\t\t}\n\n\t\t\t\tif (options?.metadata?.keyvalues) {\n\t\t\t\t\tmetadata += `,keyvalues ${btoa(JSON.stringify(options.metadata.keyvalues))}`;\n\t\t\t\t}\n\n\t\t\t\tif (options?.streamable) {\n\t\t\t\t\tmetadata += `,streamable ${btoa(\"true\")}`;\n\t\t\t\t}\n\n\t\t\t\t// Initialize TUS upload\n\t\t\t\tconst urlReq = await fetch(url, {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"Upload-Length\": `${file.size}`,\n\t\t\t\t\t\t\"Upload-Metadata\": metadata,\n\t\t\t\t\t\t...headers,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tif (!urlReq.ok) {\n\t\t\t\t\tconst errorData = await urlReq.text();\n\t\t\t\t\tif (urlReq.status === 401 || urlReq.status === 403) {\n\t\t\t\t\t\tthrow new AuthenticationError(\n\t\t\t\t\t\t\t`Authentication failed: ${errorData}`,\n\t\t\t\t\t\t\turlReq.status,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\terror: errorData,\n\t\t\t\t\t\t\t\tcode: \"AUTH_ERROR\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tthrow new NetworkError(\"Error initializing upload\", urlReq.status, {\n\t\t\t\t\t\terror: errorData,\n\t\t\t\t\t\tcode: \"HTTP_ERROR\",\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst uploadUrl = urlReq.headers.get(\"Location\");\n\t\t\t\tif (!uploadUrl) {\n\t\t\t\t\tthrow new NetworkError(\"Upload URL not provided\", urlReq.status, {\n\t\t\t\t\t\terror: \"No location header found\",\n\t\t\t\t\t\tcode: \"HTTP_ERROR\",\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tuploadUrlRef.current = uploadUrl;\n\n\t\t\t\t// Start chunked upload\n\t\t\t\tcontinueChunkedUpload();\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof Error) {\n\t\t\t\t\tsetError(err);\n\t\t\t\t} else {\n\t\t\t\t\tsetError(new Error(\"Unknown error during upload initialization\"));\n\t\t\t\t}\n\t\t\t\tsetLoading(false);\n\t\t\t}\n\t\t},\n\t\t[resetState, continueChunkedUpload],\n\t);\n\n\t// Cleanup on unmount\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tcancelledRef.current = true;\n\t\t};\n\t}, []);\n\n\treturn {\n\t\tprogress,\n\t\tloading,\n\t\terror,\n\t\tuploadResponse,\n\t\tupload,\n\t\tpause,\n\t\tresume,\n\t\tcancel,\n\t};\n};\n"]}
@@ -1,3 +1,271 @@
1
- export { AuthenticationError, NetworkError, PinataError, ValidationError, convertToDesiredGateway as convert, useUpload } from '../chunk-7UIMBFJ5.mjs';
1
+ import { NetworkError, AuthenticationError } from '../chunk-ME652TQB.mjs';
2
+ export { AuthenticationError, NetworkError, PinataError, ValidationError, convertToDesiredGateway as convert } from '../chunk-ME652TQB.mjs';
3
+ import { useState, useRef, useCallback, useEffect } from 'react';
4
+
5
+ var LARGE_FILE_THRESHOLD = 94371840;
6
+ var BASE_CHUNK_SIZE = 262144;
7
+ var DEFAULT_CHUNKS = 20 * 10;
8
+ var normalizeChunkSize = (size) => {
9
+ if (size < BASE_CHUNK_SIZE) {
10
+ return BASE_CHUNK_SIZE;
11
+ }
12
+ return Math.floor(size / BASE_CHUNK_SIZE) * BASE_CHUNK_SIZE;
13
+ };
14
+ var useUpload = () => {
15
+ const [progress, setProgress] = useState(0);
16
+ const [loading, setLoading] = useState(false);
17
+ const [error, setError] = useState(null);
18
+ const [uploadResponse, setUploadResponse] = useState(
19
+ null
20
+ );
21
+ const uploadUrlRef = useRef(null);
22
+ const pausedRef = useRef(false);
23
+ const cancelledRef = useRef(false);
24
+ const uploadOffsetRef = useRef(0);
25
+ const fileRef = useRef(null);
26
+ const headersRef = useRef({});
27
+ const lastResponseHeadersRef = useRef(null);
28
+ const chunkSizeRef = useRef(BASE_CHUNK_SIZE * DEFAULT_CHUNKS);
29
+ const resetState = useCallback(() => {
30
+ setProgress(0);
31
+ setError(null);
32
+ setUploadResponse(null);
33
+ uploadUrlRef.current = null;
34
+ pausedRef.current = false;
35
+ cancelledRef.current = false;
36
+ uploadOffsetRef.current = 0;
37
+ fileRef.current = null;
38
+ }, []);
39
+ const pause = useCallback(() => {
40
+ pausedRef.current = true;
41
+ }, []);
42
+ const resume = useCallback(() => {
43
+ if (pausedRef.current && uploadUrlRef.current && fileRef.current) {
44
+ pausedRef.current = false;
45
+ continueChunkedUpload();
46
+ }
47
+ }, []);
48
+ const cancel = useCallback(() => {
49
+ cancelledRef.current = true;
50
+ setLoading(false);
51
+ }, []);
52
+ const continueChunkedUpload = useCallback(async () => {
53
+ if (!uploadUrlRef.current || !fileRef.current) return;
54
+ try {
55
+ if (cancelledRef.current) {
56
+ resetState();
57
+ return;
58
+ }
59
+ if (pausedRef.current) return;
60
+ const file = fileRef.current;
61
+ const fileSize = file.size;
62
+ const offset = uploadOffsetRef.current;
63
+ const chunkSize = chunkSizeRef.current;
64
+ if (offset >= fileSize) {
65
+ await finalizeUpload();
66
+ return;
67
+ }
68
+ const endOffset = Math.min(offset + chunkSize, fileSize);
69
+ const chunk = file.slice(offset, endOffset);
70
+ const uploadReq = await fetch(uploadUrlRef.current, {
71
+ method: "PATCH",
72
+ headers: {
73
+ "Content-Type": "application/offset+octet-stream",
74
+ "Upload-Offset": offset.toString(),
75
+ ...headersRef.current
76
+ },
77
+ body: chunk
78
+ });
79
+ lastResponseHeadersRef.current = uploadReq.headers;
80
+ if (!uploadReq.ok) {
81
+ const errorData = await uploadReq.text();
82
+ throw new NetworkError(
83
+ `HTTP error during chunk upload: ${errorData}`,
84
+ uploadReq.status,
85
+ {
86
+ error: errorData,
87
+ code: "HTTP_ERROR",
88
+ metadata: { requestUrl: uploadReq.url }
89
+ }
90
+ );
91
+ }
92
+ const newOffset = endOffset;
93
+ uploadOffsetRef.current = newOffset;
94
+ const newProgress = Math.min(newOffset / fileSize * 100, 99.9);
95
+ setProgress(newProgress);
96
+ continueChunkedUpload();
97
+ } catch (err) {
98
+ if (err instanceof Error) {
99
+ setError(err);
100
+ } else {
101
+ setError(new Error("Unknown error during upload"));
102
+ }
103
+ setLoading(false);
104
+ }
105
+ }, [resetState]);
106
+ const finalizeUpload = useCallback(async () => {
107
+ if (!uploadUrlRef.current || !fileRef.current) return;
108
+ try {
109
+ let cid = null;
110
+ if (lastResponseHeadersRef.current) {
111
+ cid = lastResponseHeadersRef.current.get("upload-cid");
112
+ }
113
+ setUploadResponse(cid);
114
+ setProgress(100);
115
+ setLoading(false);
116
+ } catch (err) {
117
+ if (err instanceof Error) {
118
+ setError(err);
119
+ } else {
120
+ setError(new Error("Unknown error during upload finalization"));
121
+ }
122
+ setLoading(false);
123
+ }
124
+ }, []);
125
+ const simpleUpload = async (file, network, url, options) => {
126
+ try {
127
+ const formData = new FormData();
128
+ formData.append("file", file, file.name);
129
+ formData.append("network", network);
130
+ formData.append("name", options?.metadata?.name || file.name);
131
+ if (options?.groupId) {
132
+ formData.append("group_id", options.groupId);
133
+ }
134
+ if (options?.metadata?.keyvalues) {
135
+ formData.append(
136
+ "keyvalues",
137
+ JSON.stringify(options.metadata.keyvalues)
138
+ );
139
+ }
140
+ if (options?.streamable) {
141
+ formData.append("streamable", "true");
142
+ }
143
+ const request = await fetch(url, {
144
+ method: "POST",
145
+ headers: headersRef.current,
146
+ body: formData
147
+ });
148
+ if (!request.ok) {
149
+ const errorData = await request.text();
150
+ if (request.status === 401 || request.status === 403) {
151
+ throw new AuthenticationError(
152
+ `Authentication failed: ${errorData}`,
153
+ request.status,
154
+ {
155
+ error: errorData,
156
+ code: "AUTH_ERROR",
157
+ metadata: { requestUrl: request.url }
158
+ }
159
+ );
160
+ }
161
+ throw new NetworkError(`HTTP error: ${errorData}`, request.status, {
162
+ error: errorData,
163
+ code: "HTTP_ERROR",
164
+ metadata: { requestUrl: request.url }
165
+ });
166
+ }
167
+ const res = await request.json();
168
+ setUploadResponse(res.data);
169
+ setProgress(100);
170
+ setLoading(false);
171
+ } catch (err) {
172
+ if (err instanceof Error) {
173
+ setError(err);
174
+ } else {
175
+ setError(new Error("Unknown error during upload"));
176
+ }
177
+ setLoading(false);
178
+ }
179
+ };
180
+ const upload = useCallback(
181
+ async (file, network, url, options) => {
182
+ try {
183
+ resetState();
184
+ setLoading(true);
185
+ fileRef.current = file;
186
+ const headers = { Source: "sdk/react" };
187
+ headersRef.current = headers;
188
+ if (options?.chunkSize && options.chunkSize > 0) {
189
+ chunkSizeRef.current = normalizeChunkSize(options.chunkSize);
190
+ } else {
191
+ chunkSizeRef.current = BASE_CHUNK_SIZE * DEFAULT_CHUNKS;
192
+ }
193
+ if (file.size <= LARGE_FILE_THRESHOLD) {
194
+ await simpleUpload(file, network, url, options);
195
+ return;
196
+ }
197
+ let metadata = `filename ${btoa(file.name)},filetype ${btoa(file.type)},network ${btoa(network)}`;
198
+ if (options?.groupId) {
199
+ metadata += `,group_id ${btoa(options.groupId)}`;
200
+ }
201
+ if (options?.metadata?.keyvalues) {
202
+ metadata += `,keyvalues ${btoa(JSON.stringify(options.metadata.keyvalues))}`;
203
+ }
204
+ if (options?.streamable) {
205
+ metadata += `,streamable ${btoa("true")}`;
206
+ }
207
+ const urlReq = await fetch(url, {
208
+ method: "POST",
209
+ headers: {
210
+ "Upload-Length": `${file.size}`,
211
+ "Upload-Metadata": metadata,
212
+ ...headers
213
+ }
214
+ });
215
+ if (!urlReq.ok) {
216
+ const errorData = await urlReq.text();
217
+ if (urlReq.status === 401 || urlReq.status === 403) {
218
+ throw new AuthenticationError(
219
+ `Authentication failed: ${errorData}`,
220
+ urlReq.status,
221
+ {
222
+ error: errorData,
223
+ code: "AUTH_ERROR"
224
+ }
225
+ );
226
+ }
227
+ throw new NetworkError("Error initializing upload", urlReq.status, {
228
+ error: errorData,
229
+ code: "HTTP_ERROR"
230
+ });
231
+ }
232
+ const uploadUrl = urlReq.headers.get("Location");
233
+ if (!uploadUrl) {
234
+ throw new NetworkError("Upload URL not provided", urlReq.status, {
235
+ error: "No location header found",
236
+ code: "HTTP_ERROR"
237
+ });
238
+ }
239
+ uploadUrlRef.current = uploadUrl;
240
+ continueChunkedUpload();
241
+ } catch (err) {
242
+ if (err instanceof Error) {
243
+ setError(err);
244
+ } else {
245
+ setError(new Error("Unknown error during upload initialization"));
246
+ }
247
+ setLoading(false);
248
+ }
249
+ },
250
+ [resetState, continueChunkedUpload]
251
+ );
252
+ useEffect(() => {
253
+ return () => {
254
+ cancelledRef.current = true;
255
+ };
256
+ }, []);
257
+ return {
258
+ progress,
259
+ loading,
260
+ error,
261
+ uploadResponse,
262
+ upload,
263
+ pause,
264
+ resume,
265
+ cancel
266
+ };
267
+ };
268
+
269
+ export { useUpload };
2
270
  //# sourceMappingURL=index.mjs.map
3
271
  //# sourceMappingURL=index.mjs.map