@@ -2,71 +2,99 @@ import { UseMutateAsyncFunction } from '@tanstack/react-query';
2
2
3
3
import { UploadSignedUrlInput } from './schemas' ;
4
4
5
- export const fetchFile = ( url : string , metadata ?: string [ ] ) => async ( ) => {
5
+ /**
6
+ * Fetches a file from the specified URL and returns file information.
7
+ * Designed to be used as a `queryFn` in a `useQuery`.
8
+ *
9
+ * @param url The URL from which the file should be fetched.
10
+ * @param [metadata] The metadata of the file you want to retrieve.
11
+ * @returns A Promise that resolves to an object containing information about the file.
12
+ *
13
+ * @example
14
+ * // Usage with Tanstack Query's useQuery:
15
+ * const fileQuery = useQuery({
16
+ queryKey: ['fileKey', url],
17
+ queryFn: () => fetchFile(url, ['name']),
18
+ enabled: !!url,
19
+ });
20
+ */
21
+ export const fetchFile = async ( url : string , metadata ?: string [ ] ) => {
6
22
const fileResponse = await fetch ( url ) ;
7
23
if ( ! fileResponse . ok ) {
8
24
throw new Error ( 'Could not fetch the file' ) ;
9
25
}
10
26
11
27
const lastModifiedDateHeader = fileResponse . headers . get ( 'Last-Modified' ) ;
28
+ const defaultFileData = {
29
+ fileUrl : url ,
30
+ size : fileResponse . headers . get ( 'Content-Length' ) ?? undefined ,
31
+ type : fileResponse . headers . get ( 'Content-Type' ) ?? undefined ,
32
+ lastModifiedDate : lastModifiedDateHeader
33
+ ? new Date ( lastModifiedDateHeader )
34
+ : new Date ( ) ,
35
+ } ;
12
36
13
- return ( metadata || [ ] ) . reduce (
14
- ( file , currentMetadata ) => {
15
- return {
16
- ...file ,
17
- [ currentMetadata ] : fileResponse . headers . get (
18
- `x-amz-meta-${ currentMetadata } `
19
- ) ,
20
- } ;
21
- } ,
22
- {
23
- fileUrl : url ,
24
- size : fileResponse . headers . get ( 'Content-Length' ) ?? undefined ,
25
- type : fileResponse . headers . get ( 'Content-Type' ) ?? undefined ,
26
- lastModifiedDate : lastModifiedDateHeader
27
- ? new Date ( lastModifiedDateHeader )
28
- : new Date ( ) ,
29
- }
30
- ) ;
37
+ if ( ! metadata ) {
38
+ return defaultFileData ;
39
+ }
40
+
41
+ return metadata . reduce ( ( file , metadataKey ) => {
42
+ return {
43
+ ...file ,
44
+ [ metadataKey ] : fileResponse . headers . get ( `x-amz-meta-${ metadataKey } ` ) ,
45
+ } ;
46
+ } , defaultFileData ) ;
31
47
} ;
32
48
33
- export const uploadFile =
34
- (
35
- getPresignedUrl : UseMutateAsyncFunction <
36
- { signedUrl : string ; futureFileUrl : string } ,
37
- unknown ,
38
- UploadSignedUrlInput | void
39
- >
40
- ) =>
41
- async (
42
- file ?: File ,
43
- {
44
- metadata,
45
- } : {
46
- metadata ?: Record < string , string > ;
47
- } = { }
48
- ) => {
49
- if ( ! file ) {
50
- return {
51
- fileUrl : undefined ,
52
- } ;
53
- }
49
+ /**
50
+ * Asynchronously uploads a file to a server using a presigned URL.
51
+ * Designed to be used as a `mutationFn` in a `useMutation`.
52
+ *
53
+ * @param getPresignedUrl
54
+ * - An asyncMutation that is used to obtain the presigned URL and the future URL where the file will be accessible.
55
+ *
56
+ * @param file - The file object to upload.
57
+ * @param metadata - Optional metadata for the file, which will be sent to the server when generating the presigned URL.
58
+ *
59
+ * @returns A promise that resolves to an object containing the URL of the uploaded file,
60
+ * or undefined if no file was provided.
61
+ *
62
+ * @example
63
+ * // Usage with Tanstack Query's useMutation:
64
+ * const getPresignedUrl = trpc.routeToGetPresignedUrl.useMutation();
65
+ const fileUpload = useMutation({
66
+ mutationFn: (file?: File) => uploadFile(getPresignedUrl.mutateAsync, file),
67
+ });
68
+ */
69
+ export const uploadFile = async (
70
+ getPresignedUrl : UseMutateAsyncFunction <
71
+ { signedUrl : string ; futureFileUrl : string } ,
72
+ unknown ,
73
+ UploadSignedUrlInput | void
74
+ > ,
75
+ file ?: File ,
76
+ metadata : Record < string , string > = { }
77
+ ) => {
78
+ if ( ! file ) {
79
+ return {
80
+ fileUrl : undefined ,
81
+ } ;
82
+ }
54
83
55
- console . log ( file . name + ' uploaded' ) ;
56
- const { signedUrl, futureFileUrl } = await getPresignedUrl ( {
57
- metadata : {
58
- name : file . name ,
59
- ...metadata ,
60
- } ,
61
- } ) ;
84
+ const { signedUrl, futureFileUrl } = await getPresignedUrl ( {
85
+ metadata : {
86
+ name : file . name ,
87
+ ...metadata ,
88
+ } ,
89
+ } ) ;
62
90
63
- await fetch ( signedUrl , {
64
- method : 'PUT' ,
65
- headers : { 'Content-Type' : file . type } ,
66
- body : file ,
67
- } ) ;
91
+ await fetch ( signedUrl , {
92
+ method : 'PUT' ,
93
+ headers : { 'Content-Type' : file . type } ,
94
+ body : file ,
95
+ } ) ;
68
96
69
- return {
70
- fileUrl : futureFileUrl ,
71
- } as const ;
72
- } ;
97
+ return {
98
+ fileUrl : futureFileUrl ,
99
+ } as const ;
100
+ } ;
0 commit comments