@depup/uploadthing 7.7.4-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +33 -0
- package/changes.json +18 -0
- package/client/index.cjs +331 -0
- package/client/index.d.cts +36 -0
- package/client/index.d.cts.map +1 -0
- package/client/index.d.ts +36 -0
- package/client/index.d.ts.map +1 -0
- package/client/index.js +286 -0
- package/client/index.js.map +1 -0
- package/client-future/index.cjs +426 -0
- package/client-future/index.d.cts +373 -0
- package/client-future/index.d.cts.map +1 -0
- package/client-future/index.d.ts +373 -0
- package/client-future/index.d.ts.map +1 -0
- package/client-future/index.js +383 -0
- package/client-future/index.js.map +1 -0
- package/dist/chunk-CUT6urMc.cjs +30 -0
- package/dist/deprecations-DPGpmqha.cjs +13 -0
- package/dist/deprecations-pLmw6Ytd.js +8 -0
- package/dist/deprecations-pLmw6Ytd.js.map +1 -0
- package/dist/package-BQ_k22T9.cjs +11 -0
- package/dist/package-DpScpvTA.js +6 -0
- package/dist/package-DpScpvTA.js.map +1 -0
- package/dist/shared-schemas-BmG5ARoX.js +82 -0
- package/dist/shared-schemas-BmG5ARoX.js.map +1 -0
- package/dist/shared-schemas-CG9VaBtT.cjs +129 -0
- package/dist/to-web-request-BQtxSXgE.cjs +98 -0
- package/dist/to-web-request-DhP0wXG-.js +87 -0
- package/dist/to-web-request-DhP0wXG-.js.map +1 -0
- package/dist/types-Bs3w2d_3.d.ts +627 -0
- package/dist/types-Bs3w2d_3.d.ts.map +1 -0
- package/dist/types-DiVC1t2V.d.cts +625 -0
- package/dist/types-DiVC1t2V.d.cts.map +1 -0
- package/dist/upload-builder-BUa7tovh.d.cts +32 -0
- package/dist/upload-builder-BUa7tovh.d.cts.map +1 -0
- package/dist/upload-builder-BcFawEj0.d.ts +32 -0
- package/dist/upload-builder-BcFawEj0.d.ts.map +1 -0
- package/dist/upload-builder-BlFOAnsv.js +699 -0
- package/dist/upload-builder-BlFOAnsv.js.map +1 -0
- package/dist/upload-builder-D6Ken9H0.cjs +794 -0
- package/dist/ut-reporter-BHoyNnzW.cjs +120 -0
- package/dist/ut-reporter-Dlppchbx.js +103 -0
- package/dist/ut-reporter-Dlppchbx.js.map +1 -0
- package/effect-platform/index.cjs +22 -0
- package/effect-platform/index.d.cts +54 -0
- package/effect-platform/index.d.cts.map +1 -0
- package/effect-platform/index.d.ts +54 -0
- package/effect-platform/index.d.ts.map +1 -0
- package/effect-platform/index.js +19 -0
- package/effect-platform/index.js.map +1 -0
- package/express/index.cjs +30 -0
- package/express/index.d.cts +28 -0
- package/express/index.d.cts.map +1 -0
- package/express/index.d.ts +28 -0
- package/express/index.d.ts.map +1 -0
- package/express/index.js +27 -0
- package/express/index.js.map +1 -0
- package/fastify/index.cjs +27 -0
- package/fastify/index.d.cts +28 -0
- package/fastify/index.d.cts.map +1 -0
- package/fastify/index.d.ts +28 -0
- package/fastify/index.d.ts.map +1 -0
- package/fastify/index.js +24 -0
- package/fastify/index.js.map +1 -0
- package/h3/index.cjs +20 -0
- package/h3/index.d.cts +28 -0
- package/h3/index.d.cts.map +1 -0
- package/h3/index.d.ts +28 -0
- package/h3/index.d.ts.map +1 -0
- package/h3/index.js +17 -0
- package/h3/index.js.map +1 -0
- package/next/index.cjs +22 -0
- package/next/index.d.cts +30 -0
- package/next/index.d.cts.map +1 -0
- package/next/index.d.ts +30 -0
- package/next/index.d.ts.map +1 -0
- package/next/index.js +19 -0
- package/next/index.js.map +1 -0
- package/next-legacy/index.cjs +28 -0
- package/next-legacy/index.d.cts +28 -0
- package/next-legacy/index.d.cts.map +1 -0
- package/next-legacy/index.d.ts +28 -0
- package/next-legacy/index.d.ts.map +1 -0
- package/next-legacy/index.js +25 -0
- package/next-legacy/index.js.map +1 -0
- package/package.json +210 -0
- package/remix/index.cjs +22 -0
- package/remix/index.d.cts +30 -0
- package/remix/index.d.cts.map +1 -0
- package/remix/index.d.ts +30 -0
- package/remix/index.d.ts.map +1 -0
- package/remix/index.js +19 -0
- package/remix/index.js.map +1 -0
- package/server/index.cjs +414 -0
- package/server/index.d.cts +211 -0
- package/server/index.d.cts.map +1 -0
- package/server/index.d.ts +213 -0
- package/server/index.d.ts.map +1 -0
- package/server/index.js +405 -0
- package/server/index.js.map +1 -0
- package/tw/index.cjs +70 -0
- package/tw/index.d.cts +29 -0
- package/tw/index.d.cts.map +1 -0
- package/tw/index.d.ts +29 -0
- package/tw/index.d.ts.map +1 -0
- package/tw/index.js +74 -0
- package/tw/index.js.map +1 -0
- package/tw/v4.css +11 -0
- package/types/index.cjs +3 -0
- package/types/index.d.cts +2 -0
- package/types/index.d.ts +2 -0
- package/types/index.js +3 -0
package/client/index.js
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { version } from "../dist/package-DpScpvTA.js";
|
|
2
|
+
import { createDeferred, createUTReporter, generateTraceHeaders } from "../dist/ut-reporter-Dlppchbx.js";
|
|
3
|
+
import { logDeprecationWarning } from "../dist/deprecations-pLmw6Ytd.js";
|
|
4
|
+
import * as Arr from "effect/Array";
|
|
5
|
+
import * as Micro from "effect/Micro";
|
|
6
|
+
import { FetchContext, UploadAbortedError, UploadAbortedError as UploadAbortedError$1, UploadPausedError, UploadPausedError as UploadPausedError$1, UploadThingError, allowedContentTextLabelGenerator, bytesToFileSize, createIdentityProxy, fetchEff, fileSizeToBytes, generateClientDropzoneAccept, generateMimeTypes, generatePermittedFileTypes, matchFileType, objectKeys, resolveMaybeUrlArg } from "@uploadthing/shared";
|
|
7
|
+
import { unsafeCoerce } from "effect/Function";
|
|
8
|
+
import { hasProperty, isRecord } from "effect/Predicate";
|
|
9
|
+
|
|
10
|
+
//#region src/_internal/upload-browser.ts
|
|
11
|
+
const uploadWithProgress = (file, rangeStart, presigned, opts) => Micro.async((resume) => {
|
|
12
|
+
const xhr = new XMLHttpRequest();
|
|
13
|
+
xhr.open("PUT", presigned.url, true);
|
|
14
|
+
xhr.setRequestHeader("Range", `bytes=${rangeStart}-`);
|
|
15
|
+
xhr.setRequestHeader("x-uploadthing-version", version);
|
|
16
|
+
xhr.setRequestHeader("b3", opts.traceHeaders.b3);
|
|
17
|
+
xhr.setRequestHeader("traceparent", opts.traceHeaders.traceparent);
|
|
18
|
+
xhr.responseType = "json";
|
|
19
|
+
let previousLoaded = 0;
|
|
20
|
+
xhr.upload.addEventListener("progress", ({ loaded }) => {
|
|
21
|
+
const delta = loaded - previousLoaded;
|
|
22
|
+
opts.onUploadProgress?.({
|
|
23
|
+
loaded,
|
|
24
|
+
delta
|
|
25
|
+
});
|
|
26
|
+
previousLoaded = loaded;
|
|
27
|
+
});
|
|
28
|
+
xhr.addEventListener("load", () => {
|
|
29
|
+
if (xhr.status >= 200 && xhr.status < 300 && isRecord(xhr.response)) if (hasProperty(xhr.response, "error")) resume(new UploadThingError({
|
|
30
|
+
code: "UPLOAD_FAILED",
|
|
31
|
+
message: String(xhr.response.error),
|
|
32
|
+
data: xhr.response
|
|
33
|
+
}));
|
|
34
|
+
else resume(Micro.succeed(xhr.response));
|
|
35
|
+
else resume(new UploadThingError({
|
|
36
|
+
code: "UPLOAD_FAILED",
|
|
37
|
+
message: `XHR failed ${xhr.status} ${xhr.statusText}`,
|
|
38
|
+
data: xhr.response
|
|
39
|
+
}));
|
|
40
|
+
});
|
|
41
|
+
xhr.addEventListener("error", () => {
|
|
42
|
+
resume(new UploadThingError({ code: "UPLOAD_FAILED" }));
|
|
43
|
+
});
|
|
44
|
+
const formData = new FormData();
|
|
45
|
+
/**
|
|
46
|
+
* iOS/React Native FormData handling requires special attention:
|
|
47
|
+
*
|
|
48
|
+
* Issue: In React Native, iOS crashes with "attempt to insert nil object" when appending File directly
|
|
49
|
+
* to FormData. This happens because iOS tries to create NSDictionary from the file object and expects
|
|
50
|
+
* specific structure {uri, type, name}.
|
|
51
|
+
*
|
|
52
|
+
*
|
|
53
|
+
* Note: Don't try to use Blob or modify File object - iOS specifically needs plain object
|
|
54
|
+
* with these properties to create valid NSDictionary.
|
|
55
|
+
*/
|
|
56
|
+
if ("uri" in file) formData.append("file", {
|
|
57
|
+
uri: file.uri,
|
|
58
|
+
type: file.type,
|
|
59
|
+
name: file.name,
|
|
60
|
+
...rangeStart > 0 && { range: rangeStart }
|
|
61
|
+
});
|
|
62
|
+
else formData.append("file", rangeStart > 0 ? file.slice(rangeStart) : file);
|
|
63
|
+
xhr.send(formData);
|
|
64
|
+
return Micro.sync(() => xhr.abort());
|
|
65
|
+
});
|
|
66
|
+
const uploadFile = (file, presigned, opts) => fetchEff(presigned.url, {
|
|
67
|
+
method: "HEAD",
|
|
68
|
+
headers: opts.traceHeaders
|
|
69
|
+
}).pipe(Micro.map(({ headers }) => parseInt(headers.get("x-ut-range-start") ?? "0", 10)), Micro.tap((start) => opts.onUploadProgress?.({
|
|
70
|
+
delta: start,
|
|
71
|
+
loaded: start
|
|
72
|
+
})), Micro.flatMap((start) => uploadWithProgress(file, start, presigned, {
|
|
73
|
+
traceHeaders: opts.traceHeaders,
|
|
74
|
+
onUploadProgress: (progressEvent) => opts.onUploadProgress?.({
|
|
75
|
+
delta: progressEvent.delta,
|
|
76
|
+
loaded: progressEvent.loaded + start
|
|
77
|
+
})
|
|
78
|
+
})), Micro.map(unsafeCoerce), Micro.map((uploadResponse) => ({
|
|
79
|
+
name: file.name,
|
|
80
|
+
size: file.size,
|
|
81
|
+
key: presigned.key,
|
|
82
|
+
lastModified: file.lastModified,
|
|
83
|
+
serverData: uploadResponse.serverData,
|
|
84
|
+
get url() {
|
|
85
|
+
logDeprecationWarning("`file.url` is deprecated and will be removed in uploadthing v9. Use `file.ufsUrl` instead.");
|
|
86
|
+
return uploadResponse.url;
|
|
87
|
+
},
|
|
88
|
+
get appUrl() {
|
|
89
|
+
logDeprecationWarning("`file.appUrl` is deprecated and will be removed in uploadthing v9. Use `file.ufsUrl` instead.");
|
|
90
|
+
return uploadResponse.appUrl;
|
|
91
|
+
},
|
|
92
|
+
ufsUrl: uploadResponse.ufsUrl,
|
|
93
|
+
customId: presigned.customId,
|
|
94
|
+
type: file.type,
|
|
95
|
+
fileHash: uploadResponse.fileHash
|
|
96
|
+
})));
|
|
97
|
+
const uploadFilesInternal = (endpoint, opts) => {
|
|
98
|
+
const traceHeaders = generateTraceHeaders();
|
|
99
|
+
const reportEventToUT = createUTReporter({
|
|
100
|
+
endpoint: String(endpoint),
|
|
101
|
+
package: opts.package,
|
|
102
|
+
url: opts.url,
|
|
103
|
+
headers: opts.headers,
|
|
104
|
+
traceHeaders
|
|
105
|
+
});
|
|
106
|
+
const totalSize = opts.files.reduce((acc, f) => acc + f.size, 0);
|
|
107
|
+
let totalLoaded = 0;
|
|
108
|
+
return Micro.flatMap(reportEventToUT("upload", {
|
|
109
|
+
input: "input" in opts ? opts.input : null,
|
|
110
|
+
files: opts.files.map((f) => ({
|
|
111
|
+
name: f.name,
|
|
112
|
+
size: f.size,
|
|
113
|
+
type: f.type,
|
|
114
|
+
lastModified: f.lastModified
|
|
115
|
+
}))
|
|
116
|
+
}), (presigneds) => Micro.forEach(presigneds, (presigned, i) => Micro.flatMap(Micro.sync(() => opts.onUploadBegin?.({ file: opts.files[i].name })), () => uploadFile(opts.files[i], presigned, {
|
|
117
|
+
traceHeaders,
|
|
118
|
+
onUploadProgress: (ev) => {
|
|
119
|
+
totalLoaded += ev.delta;
|
|
120
|
+
opts.onUploadProgress?.({
|
|
121
|
+
file: opts.files[i],
|
|
122
|
+
progress: ev.loaded / opts.files[i].size * 100,
|
|
123
|
+
loaded: ev.loaded,
|
|
124
|
+
delta: ev.delta,
|
|
125
|
+
totalLoaded,
|
|
126
|
+
totalProgress: totalLoaded / totalSize
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
})), { concurrency: 6 }));
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/client.ts
|
|
134
|
+
const version$1 = version;
|
|
135
|
+
/**
|
|
136
|
+
* Validate that a file is of a valid type given a route config
|
|
137
|
+
* @public
|
|
138
|
+
*/
|
|
139
|
+
const isValidFileType = (file, routeConfig) => Micro.runSync(matchFileType(file, objectKeys(routeConfig)).pipe(Micro.map((type) => file.type.includes(type)), Micro.orElseSucceed(() => false)));
|
|
140
|
+
/**
|
|
141
|
+
* Validate that a file is of a valid size given a route config
|
|
142
|
+
* @public
|
|
143
|
+
*/
|
|
144
|
+
const isValidFileSize = (file, routeConfig) => Micro.runSync(matchFileType(file, objectKeys(routeConfig)).pipe(Micro.flatMap((type) => fileSizeToBytes(routeConfig[type].maxFileSize)), Micro.map((maxFileSize) => file.size <= maxFileSize), Micro.orElseSucceed(() => false)));
|
|
145
|
+
/**
|
|
146
|
+
* Generate a typed uploader for a given FileRouter
|
|
147
|
+
* @public
|
|
148
|
+
*/
|
|
149
|
+
const genUploader = (initOpts) => {
|
|
150
|
+
const routeRegistry = createIdentityProxy();
|
|
151
|
+
const controllableUpload = async (slug, opts) => {
|
|
152
|
+
const uploads = /* @__PURE__ */ new Map();
|
|
153
|
+
const endpoint = typeof slug === "function" ? slug(routeRegistry) : slug;
|
|
154
|
+
const traceHeaders = generateTraceHeaders();
|
|
155
|
+
const utReporter = createUTReporter({
|
|
156
|
+
endpoint: String(endpoint),
|
|
157
|
+
package: initOpts?.package ?? "uploadthing/client",
|
|
158
|
+
url: resolveMaybeUrlArg(initOpts?.url),
|
|
159
|
+
headers: opts.headers,
|
|
160
|
+
traceHeaders
|
|
161
|
+
});
|
|
162
|
+
const fetchFn = initOpts?.fetch ?? window.fetch;
|
|
163
|
+
const presigneds = await Micro.runPromise(utReporter("upload", {
|
|
164
|
+
input: "input" in opts ? opts.input : null,
|
|
165
|
+
files: opts.files.map((f) => ({
|
|
166
|
+
name: f.name,
|
|
167
|
+
size: f.size,
|
|
168
|
+
type: f.type,
|
|
169
|
+
lastModified: f.lastModified
|
|
170
|
+
}))
|
|
171
|
+
}).pipe(Micro.provideService(FetchContext, fetchFn)));
|
|
172
|
+
const totalSize = opts.files.reduce((acc, f) => acc + f.size, 0);
|
|
173
|
+
let totalLoaded = 0;
|
|
174
|
+
const uploadEffect = (file, presigned) => uploadFile(file, presigned, {
|
|
175
|
+
traceHeaders,
|
|
176
|
+
onUploadProgress: (progressEvent) => {
|
|
177
|
+
totalLoaded += progressEvent.delta;
|
|
178
|
+
opts.onUploadProgress?.({
|
|
179
|
+
...progressEvent,
|
|
180
|
+
file,
|
|
181
|
+
progress: Math.round(progressEvent.loaded / file.size * 100),
|
|
182
|
+
totalLoaded,
|
|
183
|
+
totalProgress: Math.round(totalLoaded / totalSize * 100)
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}).pipe(Micro.provideService(FetchContext, fetchFn));
|
|
187
|
+
for (const [i, p] of presigneds.entries()) {
|
|
188
|
+
const file = opts.files[i];
|
|
189
|
+
if (!file) continue;
|
|
190
|
+
const deferred = createDeferred();
|
|
191
|
+
uploads.set(file, {
|
|
192
|
+
deferred,
|
|
193
|
+
presigned: p
|
|
194
|
+
});
|
|
195
|
+
Micro.runPromiseExit(uploadEffect(file, p), { signal: deferred.ac.signal }).then((result) => {
|
|
196
|
+
if (result._tag === "Success") return deferred.resolve(result.value);
|
|
197
|
+
else if (result.cause._tag === "Interrupt") throw new UploadPausedError$1();
|
|
198
|
+
throw Micro.causeSquash(result.cause);
|
|
199
|
+
}).catch((err) => {
|
|
200
|
+
if (err instanceof UploadPausedError$1) return;
|
|
201
|
+
deferred.reject(err);
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Pause an ongoing upload
|
|
206
|
+
* @param file The file upload you want to pause. Can be omitted to pause all files
|
|
207
|
+
*/
|
|
208
|
+
const pauseUpload = (file) => {
|
|
209
|
+
const files = Arr.ensure(file ?? opts.files);
|
|
210
|
+
for (const file$1 of files) {
|
|
211
|
+
const upload = uploads.get(file$1);
|
|
212
|
+
if (!upload) return;
|
|
213
|
+
if (upload.deferred.ac.signal.aborted) throw new UploadAbortedError$1();
|
|
214
|
+
upload.deferred.ac.abort();
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
/**
|
|
218
|
+
* Resume a paused upload
|
|
219
|
+
* @param file The file upload you want to resume. Can be omitted to resume all files
|
|
220
|
+
*/
|
|
221
|
+
const resumeUpload = (file) => {
|
|
222
|
+
const files = Arr.ensure(file ?? opts.files);
|
|
223
|
+
for (const file$1 of files) {
|
|
224
|
+
const upload = uploads.get(file$1);
|
|
225
|
+
if (!upload) throw "No upload found";
|
|
226
|
+
upload.deferred.ac = new AbortController();
|
|
227
|
+
Micro.runPromiseExit(uploadEffect(file$1, upload.presigned), { signal: upload.deferred.ac.signal }).then((result) => {
|
|
228
|
+
if (result._tag === "Success") return upload.deferred.resolve(result.value);
|
|
229
|
+
else if (result.cause._tag === "Interrupt") throw new UploadPausedError$1();
|
|
230
|
+
throw Micro.causeSquash(result.cause);
|
|
231
|
+
}).catch((err) => {
|
|
232
|
+
if (err instanceof UploadPausedError$1) return;
|
|
233
|
+
upload.deferred.reject(err);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
/**
|
|
238
|
+
* Wait for an upload to complete
|
|
239
|
+
* @param file The file upload you want to wait for. Can be omitted to wait for all files
|
|
240
|
+
*/
|
|
241
|
+
const done = async (file) => {
|
|
242
|
+
const promises = [];
|
|
243
|
+
const files = Arr.ensure(file ?? opts.files);
|
|
244
|
+
for (const file$1 of files) {
|
|
245
|
+
const upload = uploads.get(file$1);
|
|
246
|
+
if (!upload) throw "No upload found";
|
|
247
|
+
promises.push(upload.deferred.promise);
|
|
248
|
+
}
|
|
249
|
+
const results = await Promise.all(promises);
|
|
250
|
+
return file ? results[0] : results;
|
|
251
|
+
};
|
|
252
|
+
return {
|
|
253
|
+
pauseUpload,
|
|
254
|
+
resumeUpload,
|
|
255
|
+
done
|
|
256
|
+
};
|
|
257
|
+
};
|
|
258
|
+
/**
|
|
259
|
+
* One step upload function that both requests presigned URLs
|
|
260
|
+
* and then uploads the files to UploadThing
|
|
261
|
+
*/
|
|
262
|
+
const typedUploadFiles = (slug, opts) => {
|
|
263
|
+
const endpoint = typeof slug === "function" ? slug(routeRegistry) : slug;
|
|
264
|
+
const fetchFn = initOpts?.fetch ?? window.fetch;
|
|
265
|
+
return uploadFilesInternal(endpoint, {
|
|
266
|
+
...opts,
|
|
267
|
+
skipPolling: {},
|
|
268
|
+
url: resolveMaybeUrlArg(initOpts?.url),
|
|
269
|
+
package: initOpts?.package ?? "uploadthing/client",
|
|
270
|
+
input: opts.input
|
|
271
|
+
}).pipe(Micro.provideService(FetchContext, fetchFn), (effect) => Micro.runPromiseExit(effect, opts.signal && { signal: opts.signal })).then((exit) => {
|
|
272
|
+
if (exit._tag === "Success") return exit.value;
|
|
273
|
+
else if (exit.cause._tag === "Interrupt") throw new UploadAbortedError$1();
|
|
274
|
+
throw Micro.causeSquash(exit.cause);
|
|
275
|
+
});
|
|
276
|
+
};
|
|
277
|
+
return {
|
|
278
|
+
uploadFiles: typedUploadFiles,
|
|
279
|
+
createUpload: controllableUpload,
|
|
280
|
+
routeRegistry
|
|
281
|
+
};
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
//#endregion
|
|
285
|
+
export { UploadAbortedError, UploadPausedError, allowedContentTextLabelGenerator, bytesToFileSize, genUploader, generateClientDropzoneAccept, generateMimeTypes, generatePermittedFileTypes, isValidFileSize, isValidFileType, version$1 as version };
|
|
286
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["file: File","rangeStart: number","presigned: NewPresignedUrl","opts: {\n traceHeaders: TraceHeaders;\n onUploadProgress?:\n | ((opts: { loaded: number; delta: number }) => void)\n | undefined;\n }","opts: {\n traceHeaders: TraceHeaders;\n onUploadProgress?: (progressEvent: {\n loaded: number;\n delta: number;\n }) => void;\n }","endpoint: TEndpoint","opts: UploadFilesOptions<TRouter[TEndpoint]>","version","file: File","routeConfig: ExpandedRouteConfig","initOpts?: GenerateUploaderOptions","slug: EndpointArg<TRouter, TEndpoint>","opts: Omit<\n CreateUploadOptions<TRouter[TEndpoint]>,\n keyof GenerateUploaderOptions\n >","fetchFn: FetchEsque","presigned: NewPresignedUrl","UploadPausedError","file?: File","file","UploadAbortedError","file?: T","opts: Omit<\n UploadFilesOptions<TRouter[TEndpoint]>,\n keyof GenerateUploaderOptions\n >"],"sources":["../src/_internal/upload-browser.ts","../src/client.ts"],"sourcesContent":["import { unsafeCoerce } from \"effect/Function\";\nimport * as Micro from \"effect/Micro\";\nimport { hasProperty, isRecord } from \"effect/Predicate\";\n\nimport type { FetchContext, FetchError } from \"@uploadthing/shared\";\nimport { fetchEff, UploadThingError } from \"@uploadthing/shared\";\n\nimport { version } from \"../../package.json\";\nimport type {\n ClientUploadedFileData,\n FileRouter,\n inferEndpointOutput,\n NewPresignedUrl,\n UploadFilesOptions,\n} from \"../types\";\nimport { logDeprecationWarning } from \"./deprecations\";\nimport type { TraceHeaders } from \"./random-hex\";\nimport { generateTraceHeaders } from \"./random-hex\";\nimport type { UploadPutResult } from \"./types\";\nimport { createUTReporter } from \"./ut-reporter\";\n\nconst uploadWithProgress = (\n file: File,\n rangeStart: number,\n presigned: NewPresignedUrl,\n opts: {\n traceHeaders: TraceHeaders;\n onUploadProgress?:\n | ((opts: { loaded: number; delta: number }) => void)\n | undefined;\n },\n) =>\n Micro.async<unknown, UploadThingError, FetchContext>((resume) => {\n const xhr = new XMLHttpRequest();\n xhr.open(\"PUT\", presigned.url, true);\n xhr.setRequestHeader(\"Range\", `bytes=${rangeStart}-`);\n xhr.setRequestHeader(\"x-uploadthing-version\", version);\n xhr.setRequestHeader(\"b3\", opts.traceHeaders.b3);\n xhr.setRequestHeader(\"traceparent\", opts.traceHeaders.traceparent);\n\n xhr.responseType = \"json\";\n\n let previousLoaded = 0;\n xhr.upload.addEventListener(\"progress\", ({ loaded }) => {\n const delta = loaded - previousLoaded;\n opts.onUploadProgress?.({ loaded, delta });\n previousLoaded = loaded;\n });\n xhr.addEventListener(\"load\", () => {\n if (xhr.status >= 200 && xhr.status < 300 && isRecord(xhr.response)) {\n if (hasProperty(xhr.response, \"error\")) {\n resume(\n new UploadThingError({\n code: \"UPLOAD_FAILED\",\n message: String(xhr.response.error),\n data: xhr.response as never,\n }),\n );\n } else {\n resume(Micro.succeed(xhr.response));\n }\n } else {\n resume(\n new UploadThingError({\n code: \"UPLOAD_FAILED\",\n message: `XHR failed ${xhr.status} ${xhr.statusText}`,\n data: xhr.response as never,\n }),\n );\n }\n });\n\n // Is there a case when the client would throw and\n // ingest server not knowing about it? idts?\n xhr.addEventListener(\"error\", () => {\n resume(\n new UploadThingError({\n code: \"UPLOAD_FAILED\",\n }),\n );\n });\n\n const formData = new FormData();\n /**\n * iOS/React Native FormData handling requires special attention:\n *\n * Issue: In React Native, iOS crashes with \"attempt to insert nil object\" when appending File directly\n * to FormData. This happens because iOS tries to create NSDictionary from the file object and expects\n * specific structure {uri, type, name}.\n *\n *\n * Note: Don't try to use Blob or modify File object - iOS specifically needs plain object\n * with these properties to create valid NSDictionary.\n */\n if (\"uri\" in file) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n formData.append(\"file\", {\n uri: file.uri as string,\n type: file.type,\n name: file.name,\n ...(rangeStart > 0 && { range: rangeStart }),\n } as any);\n } else {\n formData.append(\"file\", rangeStart > 0 ? file.slice(rangeStart) : file);\n }\n xhr.send(formData);\n\n return Micro.sync(() => xhr.abort());\n });\n\nexport const uploadFile = <\n TRouter extends FileRouter,\n TEndpoint extends keyof TRouter,\n TServerOutput = inferEndpointOutput<TRouter[TEndpoint]>,\n>(\n file: File,\n presigned: NewPresignedUrl,\n opts: {\n traceHeaders: TraceHeaders;\n onUploadProgress?: (progressEvent: {\n loaded: number;\n delta: number;\n }) => void;\n },\n) =>\n fetchEff(presigned.url, {\n method: \"HEAD\",\n headers: opts.traceHeaders,\n }).pipe(\n Micro.map(({ headers }) =>\n parseInt(headers.get(\"x-ut-range-start\") ?? \"0\", 10),\n ),\n Micro.tap((start) =>\n opts.onUploadProgress?.({\n delta: start,\n loaded: start,\n }),\n ),\n Micro.flatMap((start) =>\n uploadWithProgress(file, start, presigned, {\n traceHeaders: opts.traceHeaders,\n onUploadProgress: (progressEvent) =>\n opts.onUploadProgress?.({\n delta: progressEvent.delta,\n loaded: progressEvent.loaded + start,\n }),\n }),\n ),\n Micro.map(unsafeCoerce<unknown, UploadPutResult<TServerOutput>>),\n Micro.map((uploadResponse) => ({\n name: file.name,\n size: file.size,\n key: presigned.key,\n lastModified: file.lastModified,\n serverData: uploadResponse.serverData,\n get url() {\n logDeprecationWarning(\n \"`file.url` is deprecated and will be removed in uploadthing v9. Use `file.ufsUrl` instead.\",\n );\n return uploadResponse.url;\n },\n get appUrl() {\n logDeprecationWarning(\n \"`file.appUrl` is deprecated and will be removed in uploadthing v9. Use `file.ufsUrl` instead.\",\n );\n return uploadResponse.appUrl;\n },\n ufsUrl: uploadResponse.ufsUrl,\n customId: presigned.customId,\n type: file.type,\n fileHash: uploadResponse.fileHash,\n })),\n );\n\nexport const uploadFilesInternal = <\n TRouter extends FileRouter,\n TEndpoint extends keyof TRouter,\n TServerOutput = inferEndpointOutput<TRouter[TEndpoint]>,\n>(\n endpoint: TEndpoint,\n opts: UploadFilesOptions<TRouter[TEndpoint]>,\n): Micro.Micro<\n ClientUploadedFileData<TServerOutput>[],\n UploadThingError | FetchError,\n FetchContext\n> => {\n // classic service right here\n const traceHeaders = generateTraceHeaders();\n const reportEventToUT = createUTReporter({\n endpoint: String(endpoint),\n package: opts.package,\n url: opts.url,\n headers: opts.headers,\n traceHeaders,\n });\n\n const totalSize = opts.files.reduce((acc, f) => acc + f.size, 0);\n let totalLoaded = 0;\n\n return Micro.flatMap(\n reportEventToUT(\"upload\", {\n input: \"input\" in opts ? opts.input : null,\n files: opts.files.map((f) => ({\n name: f.name,\n size: f.size,\n type: f.type,\n lastModified: f.lastModified,\n })),\n }),\n (presigneds) =>\n Micro.forEach(\n presigneds,\n (presigned, i) =>\n Micro.flatMap(\n Micro.sync(() =>\n opts.onUploadBegin?.({ file: opts.files[i]!.name }),\n ),\n () =>\n uploadFile<TRouter, TEndpoint, TServerOutput>(\n opts.files[i]!,\n presigned,\n {\n traceHeaders,\n onUploadProgress: (ev) => {\n totalLoaded += ev.delta;\n opts.onUploadProgress?.({\n file: opts.files[i]!,\n progress: (ev.loaded / opts.files[i]!.size) * 100,\n loaded: ev.loaded,\n delta: ev.delta,\n totalLoaded,\n totalProgress: totalLoaded / totalSize,\n });\n },\n },\n ),\n ),\n { concurrency: 6 },\n ),\n );\n};\n","import * as Arr from \"effect/Array\";\nimport * as Micro from \"effect/Micro\";\n\nimport type { ExpandedRouteConfig, FetchEsque } from \"@uploadthing/shared\";\nimport {\n createIdentityProxy,\n FetchContext,\n fileSizeToBytes,\n matchFileType,\n objectKeys,\n resolveMaybeUrlArg,\n UploadAbortedError,\n UploadPausedError,\n} from \"@uploadthing/shared\";\n\nimport * as pkgJson from \"../package.json\";\nimport type { Deferred } from \"./_internal/deferred\";\nimport { createDeferred } from \"./_internal/deferred\";\nimport { generateTraceHeaders } from \"./_internal/random-hex\";\nimport { uploadFile, uploadFilesInternal } from \"./_internal/upload-browser\";\nimport { createUTReporter } from \"./_internal/ut-reporter\";\nimport type {\n ClientUploadedFileData,\n CreateUploadOptions,\n EndpointArg,\n FileRouter,\n GenerateUploaderOptions,\n inferEndpointInput,\n inferEndpointOutput,\n NewPresignedUrl,\n RouteRegistry,\n UploadFilesOptions,\n} from \"./types\";\n\nexport const version = pkgJson.version;\n\nexport {\n /** @public */\n generateClientDropzoneAccept,\n /** @public */\n generateMimeTypes,\n /** @public */\n generatePermittedFileTypes,\n /** @public */\n bytesToFileSize,\n /** @public */\n allowedContentTextLabelGenerator,\n /** @public */\n UploadAbortedError,\n /** @public */\n UploadPausedError,\n} from \"@uploadthing/shared\";\n\n/**\n * Validate that a file is of a valid type given a route config\n * @public\n */\nexport const isValidFileType = (\n file: File,\n routeConfig: ExpandedRouteConfig,\n): boolean =>\n Micro.runSync(\n matchFileType(file, objectKeys(routeConfig)).pipe(\n Micro.map((type) => file.type.includes(type)),\n Micro.orElseSucceed(() => false),\n ),\n );\n\n/**\n * Validate that a file is of a valid size given a route config\n * @public\n */\nexport const isValidFileSize = (\n file: File,\n routeConfig: ExpandedRouteConfig,\n): boolean =>\n Micro.runSync(\n matchFileType(file, objectKeys(routeConfig)).pipe(\n Micro.flatMap((type) => fileSizeToBytes(routeConfig[type]!.maxFileSize)),\n Micro.map((maxFileSize) => file.size <= maxFileSize),\n Micro.orElseSucceed(() => false),\n ),\n );\n\n/**\n * Generate a typed uploader for a given FileRouter\n * @public\n */\nexport const genUploader = <TRouter extends FileRouter>(\n initOpts?: GenerateUploaderOptions,\n) => {\n const routeRegistry = createIdentityProxy<RouteRegistry<TRouter>>();\n\n const controllableUpload = async <\n TEndpoint extends keyof TRouter,\n TServerOutput = inferEndpointOutput<TRouter[TEndpoint]>,\n >(\n slug: EndpointArg<TRouter, TEndpoint>,\n opts: Omit<\n CreateUploadOptions<TRouter[TEndpoint]>,\n keyof GenerateUploaderOptions\n >,\n ) => {\n const uploads = new Map<\n File,\n {\n presigned: NewPresignedUrl;\n deferred: Deferred<ClientUploadedFileData<TServerOutput>>;\n }\n >();\n\n const endpoint = typeof slug === \"function\" ? slug(routeRegistry) : slug;\n\n const traceHeaders = generateTraceHeaders();\n const utReporter = createUTReporter({\n endpoint: String(endpoint),\n package: initOpts?.package ?? \"uploadthing/client\",\n url: resolveMaybeUrlArg(initOpts?.url),\n headers: opts.headers,\n traceHeaders,\n });\n const fetchFn: FetchEsque = initOpts?.fetch ?? window.fetch;\n\n const presigneds = await Micro.runPromise(\n utReporter(\"upload\", {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n input: \"input\" in opts ? (opts.input as any) : null,\n files: opts.files.map((f) => ({\n name: f.name,\n size: f.size,\n type: f.type,\n lastModified: f.lastModified,\n })),\n }).pipe(Micro.provideService(FetchContext, fetchFn)),\n );\n\n const totalSize = opts.files.reduce((acc, f) => acc + f.size, 0);\n let totalLoaded = 0;\n\n const uploadEffect = (file: File, presigned: NewPresignedUrl) =>\n uploadFile(file, presigned, {\n traceHeaders,\n onUploadProgress: (progressEvent) => {\n totalLoaded += progressEvent.delta;\n opts.onUploadProgress?.({\n ...progressEvent,\n file,\n progress: Math.round((progressEvent.loaded / file.size) * 100),\n totalLoaded,\n totalProgress: Math.round((totalLoaded / totalSize) * 100),\n });\n },\n }).pipe(Micro.provideService(FetchContext, fetchFn));\n\n for (const [i, p] of presigneds.entries()) {\n const file = opts.files[i];\n if (!file) continue;\n\n const deferred = createDeferred<ClientUploadedFileData<TServerOutput>>();\n uploads.set(file, { deferred, presigned: p });\n\n void Micro.runPromiseExit(uploadEffect(file, p), {\n signal: deferred.ac.signal,\n })\n .then((result) => {\n if (result._tag === \"Success\") {\n return deferred.resolve(result.value);\n } else if (result.cause._tag === \"Interrupt\") {\n throw new UploadPausedError();\n }\n throw Micro.causeSquash(result.cause);\n })\n .catch((err) => {\n if (err instanceof UploadPausedError) return;\n deferred.reject(err);\n });\n }\n\n /**\n * Pause an ongoing upload\n * @param file The file upload you want to pause. Can be omitted to pause all files\n */\n const pauseUpload = (file?: File) => {\n const files = Arr.ensure(file ?? opts.files);\n for (const file of files) {\n const upload = uploads.get(file);\n if (!upload) return;\n\n if (upload.deferred.ac.signal.aborted) {\n // Cancel the upload if it's already been paused\n throw new UploadAbortedError();\n }\n\n upload.deferred.ac.abort();\n }\n };\n\n /**\n * Resume a paused upload\n * @param file The file upload you want to resume. Can be omitted to resume all files\n */\n const resumeUpload = (file?: File) => {\n const files = Arr.ensure(file ?? opts.files);\n for (const file of files) {\n const upload = uploads.get(file);\n if (!upload) throw \"No upload found\";\n\n upload.deferred.ac = new AbortController();\n void Micro.runPromiseExit(uploadEffect(file, upload.presigned), {\n signal: upload.deferred.ac.signal,\n })\n .then((result) => {\n if (result._tag === \"Success\") {\n return upload.deferred.resolve(result.value);\n } else if (result.cause._tag === \"Interrupt\") {\n throw new UploadPausedError();\n }\n throw Micro.causeSquash(result.cause);\n })\n .catch((err) => {\n if (err instanceof UploadPausedError) return;\n upload.deferred.reject(err);\n });\n }\n };\n\n /**\n * Wait for an upload to complete\n * @param file The file upload you want to wait for. Can be omitted to wait for all files\n */\n const done = async <T extends File | void = void>(\n file?: T,\n ): Promise<\n T extends File\n ? ClientUploadedFileData<TServerOutput>\n : ClientUploadedFileData<TServerOutput>[]\n > => {\n const promises = [];\n\n const files = Arr.ensure(file ?? opts.files);\n for (const file of files) {\n const upload = uploads.get(file);\n if (!upload) throw \"No upload found\";\n\n promises.push(upload.deferred.promise);\n }\n\n const results = await Promise.all(promises);\n return (file ? results[0] : results) as never;\n };\n\n return { pauseUpload, resumeUpload, done };\n };\n\n /**\n * One step upload function that both requests presigned URLs\n * and then uploads the files to UploadThing\n */\n const typedUploadFiles = <TEndpoint extends keyof TRouter>(\n slug: EndpointArg<TRouter, TEndpoint>,\n opts: Omit<\n UploadFilesOptions<TRouter[TEndpoint]>,\n keyof GenerateUploaderOptions\n >,\n ) => {\n const endpoint = typeof slug === \"function\" ? slug(routeRegistry) : slug;\n const fetchFn: FetchEsque = initOpts?.fetch ?? window.fetch;\n\n return uploadFilesInternal<TRouter, TEndpoint>(endpoint, {\n ...opts,\n skipPolling: {} as never, // Remove in a future version, it's type right not is an ErrorMessage<T> to help migrations.\n url: resolveMaybeUrlArg(initOpts?.url),\n package: initOpts?.package ?? \"uploadthing/client\",\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n input: (opts as any).input as inferEndpointInput<TRouter[TEndpoint]>,\n })\n .pipe(Micro.provideService(FetchContext, fetchFn), (effect) =>\n Micro.runPromiseExit(effect, opts.signal && { signal: opts.signal }),\n )\n .then((exit) => {\n if (exit._tag === \"Success\") {\n return exit.value;\n } else if (exit.cause._tag === \"Interrupt\") {\n throw new UploadAbortedError();\n }\n throw Micro.causeSquash(exit.cause);\n });\n };\n\n return {\n uploadFiles: typedUploadFiles,\n createUpload: controllableUpload,\n /**\n * Identity object that can be used instead of raw strings\n * that allows \"Go to definition\" in your IDE to bring you\n * to the backend definition of a route.\n */\n routeRegistry,\n };\n};\n"],"mappings":"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"}
|