From b99e088cb6b9b5682a9018bf2600f7a3d03fcb6a Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Wed, 16 Oct 2024 10:50:32 +0200 Subject: [PATCH 01/15] chore: pass `files` to `styleFieldArg` (#1012) --- docs/src/app/(docs)/concepts/theming/page.mdx | 2 ++ packages/react/src/components/button.tsx | 18 +++++++++++------ packages/react/src/components/dropzone.tsx | 20 ++++++++++++------- packages/solid/src/components/button.tsx | 2 ++ packages/solid/src/components/dropzone.tsx | 2 ++ .../src/lib/component/UploadButton.svelte | 2 ++ .../src/lib/component/UploadDropzone.svelte | 2 ++ packages/vue/src/components/button.tsx | 2 ++ packages/vue/src/components/dropzone.tsx | 2 ++ 9 files changed, 39 insertions(+), 13 deletions(-) diff --git a/docs/src/app/(docs)/concepts/theming/page.mdx b/docs/src/app/(docs)/concepts/theming/page.mdx index 1214c08d99..d28e561f35 100644 --- a/docs/src/app/(docs)/concepts/theming/page.mdx +++ b/docs/src/app/(docs)/concepts/theming/page.mdx @@ -135,6 +135,7 @@ type ButtonCallbackArguments = { isUploading: boolean; uploadProgress: number; fileTypes: string[]; + files: File[]; }; type DropzoneCallbackArguments = { @@ -143,6 +144,7 @@ type DropzoneCallbackArguments = { uploadProgress: number; fileTypes: string[]; isDragActive: boolean; + files: File[]; }; ``` diff --git a/packages/react/src/components/button.tsx b/packages/react/src/components/button.tsx index 107fd4b865..f34304d32c 100644 --- a/packages/react/src/components/button.tsx +++ b/packages/react/src/components/button.tsx @@ -32,6 +32,7 @@ type ButtonStyleFieldCallbackArgs = { isUploading: boolean; uploadProgress: number; fileTypes: string[]; + files: File[]; }; type ButtonAppearance = { @@ -218,12 +219,17 @@ export function UploadButton< if (mode === "auto") uploadFiles(files); }); - const styleFieldArg = { - ready: state !== "readying", - isUploading: state === "uploading", - uploadProgress, - fileTypes, - } as ButtonStyleFieldCallbackArgs; + const styleFieldArg = useMemo( + () => + ({ + ready: state !== "readying", + isUploading: state === "uploading", + uploadProgress, + fileTypes, + files, + }) as ButtonStyleFieldCallbackArgs, + [fileTypes, files, state, uploadProgress], + ); const renderButton = () => { const customContent = contentFieldToContent( diff --git a/packages/react/src/components/dropzone.tsx b/packages/react/src/components/dropzone.tsx index 248549df8a..06cca2f59a 100644 --- a/packages/react/src/components/dropzone.tsx +++ b/packages/react/src/components/dropzone.tsx @@ -60,6 +60,7 @@ type DropzoneStyleFieldCallbackArgs = { uploadProgress: number; fileTypes: string[]; isDragActive: boolean; + files: File[]; }; type DropzoneAppearance = { @@ -249,13 +250,18 @@ export function UploadDropzone< if (mode === "auto") uploadFiles(filesToUpload); }); - const styleFieldArg = { - ready: state !== "readying", - isUploading: state === "uploading", - uploadProgress, - fileTypes, - isDragActive, - } as DropzoneStyleFieldCallbackArgs; + const styleFieldArg = useMemo( + () => + ({ + ready: state !== "readying", + isUploading: state === "uploading", + uploadProgress, + fileTypes, + files, + isDragActive, + }) as DropzoneStyleFieldCallbackArgs, + [fileTypes, files, state, uploadProgress, isDragActive], + ); const getUploadButtonContents = () => { const customContent = contentFieldToContent( diff --git a/packages/solid/src/components/button.tsx b/packages/solid/src/components/button.tsx index c7d32195bb..b506cad932 100644 --- a/packages/solid/src/components/button.tsx +++ b/packages/solid/src/components/button.tsx @@ -29,6 +29,7 @@ type ButtonStyleFieldCallbackArgs = { isUploading: () => boolean; uploadProgress: () => number; fileTypes: () => string[]; + files: () => File[]; }; type ButtonAppearance = { @@ -175,6 +176,7 @@ export function UploadButton< isUploading: uploadThing.isUploading, uploadProgress: uploadProgress, fileTypes: () => fileInfo().fileTypes, + files, } as ButtonStyleFieldCallbackArgs; const getButtonContent = () => { diff --git a/packages/solid/src/components/dropzone.tsx b/packages/solid/src/components/dropzone.tsx index bb7507fa60..d79df58545 100644 --- a/packages/solid/src/components/dropzone.tsx +++ b/packages/solid/src/components/dropzone.tsx @@ -53,6 +53,7 @@ type DropzoneStyleFieldCallbackArgs = { uploadProgress: () => number; fileTypes: () => string[]; isDragActive: () => boolean; + files: () => File[]; }; type DropzoneAppearance = { @@ -222,6 +223,7 @@ export const UploadDropzone = < uploadProgress: uploadProgress, fileTypes: () => fileInfo().fileTypes, isDragActive: () => isDragActive, + files, } as DropzoneStyleFieldCallbackArgs; return ( diff --git a/packages/svelte/src/lib/component/UploadButton.svelte b/packages/svelte/src/lib/component/UploadButton.svelte index 4310077f74..a05d0699da 100644 --- a/packages/svelte/src/lib/component/UploadButton.svelte +++ b/packages/svelte/src/lib/component/UploadButton.svelte @@ -38,6 +38,7 @@ isUploading: boolean; uploadProgress: number; fileTypes: string[]; + files: File[]; }; type UploadButtonAppearance = { @@ -135,6 +136,7 @@ isUploading: state === "uploading", uploadProgress, fileTypes, + files, } as ButtonStyleFieldCallbackArgs; diff --git a/packages/svelte/src/lib/component/UploadDropzone.svelte b/packages/svelte/src/lib/component/UploadDropzone.svelte index ea92c3dee0..4e0aba2c9e 100644 --- a/packages/svelte/src/lib/component/UploadDropzone.svelte +++ b/packages/svelte/src/lib/component/UploadDropzone.svelte @@ -40,6 +40,7 @@ uploadProgress: number; fileTypes: string[]; isDragActive: boolean; + files: File[]; }; type UploadDropzoneAppearance = { @@ -185,6 +186,7 @@ isUploading: $isUploading, ready, uploadProgress, + files, } satisfies DropzoneStyleFieldCallbackArgs; $: state = (() => { diff --git a/packages/vue/src/components/button.tsx b/packages/vue/src/components/button.tsx index 1c57b0cb9b..14666fa84f 100644 --- a/packages/vue/src/components/button.tsx +++ b/packages/vue/src/components/button.tsx @@ -30,6 +30,7 @@ export type ButtonStyleFieldCallbackArgs = { isUploading: boolean; uploadProgress: number; fileTypes: string[]; + files: File[]; }; export type ButtonAppearance = { @@ -199,6 +200,7 @@ export const generateUploadButton = ( isUploading: state.value === "uploading", uploadProgress: uploadProgress.value, fileTypes: permittedFileTypes.value.fileTypes, + files: files.value, }) as ButtonStyleFieldCallbackArgs, ); diff --git a/packages/vue/src/components/dropzone.tsx b/packages/vue/src/components/dropzone.tsx index 651d0bf51b..2fa98623d9 100644 --- a/packages/vue/src/components/dropzone.tsx +++ b/packages/vue/src/components/dropzone.tsx @@ -49,6 +49,7 @@ export type DropzoneStyleFieldCallbackArgs = { uploadProgress: number; fileTypes: string[]; isDragActive: boolean; + files: File[]; }; export type DropzoneAppearance = { @@ -236,6 +237,7 @@ export const generateUploadDropzone = ( uploadProgress: uploadProgress.value, fileTypes: permittedFileTypes.value.fileTypes, isDragActive: isDragActive.value, + files: files.value, }) as DropzoneStyleFieldCallbackArgs, ); From 74c94c820948ccb349aba589bdc4528f0a1f6e1b Mon Sep 17 00:00:00 2001 From: juliusmarminge Date: Wed, 16 Oct 2024 12:00:30 +0200 Subject: [PATCH 02/15] chore: remove requets log in tss example --- .../app/server/uploadthing.ts | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/examples/minimal-tanstack-start/app/server/uploadthing.ts b/examples/minimal-tanstack-start/app/server/uploadthing.ts index b664e6c096..b7307b4877 100644 --- a/examples/minimal-tanstack-start/app/server/uploadthing.ts +++ b/examples/minimal-tanstack-start/app/server/uploadthing.ts @@ -32,28 +32,18 @@ export const uploadRouter = { maxFileSize: "8GB", }, }) - .middleware(({ req, files }) => { - // Check some condition based on the incoming requrest - console.log("Request", req); - //^? + .middleware(({ req }) => { + // Check some condition based on the incoming request // if (!req.headers.get("x-some-header")) { // throw new Error("x-some-header is required"); // } - // (Optional) Label your files with a custom identifier - const filesWithMyIds = files.map((file, idx) => ({ - ...file, - customId: `${idx}-HELLO`, - })); - // Return some metadata to be stored with the file - return { foo: "bar" as const, [UTFiles]: filesWithMyIds }; + return { foo: "bar" as const }; }) .onUploadComplete(({ file, metadata }) => { metadata; // ^? - file.customId; - // ^? console.log("upload completed", file); }), } satisfies FileRouter; From 3acc199821637bda1605cd7130325e8783710908 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Wed, 23 Oct 2024 10:52:42 +0200 Subject: [PATCH 03/15] feat: support IDE feature `Go to defintion` (#1008) Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .changeset/twenty-rings-unite.md | 34 +++++++++++ .../app/(docs)/api-reference/client/page.mdx | 14 +++++ .../app/(docs)/api-reference/react/page.mdx | 48 +++++++++++++++- .../client-react/src/main.tsx | 2 +- .../client-vanilla/src/normal-upload.ts | 15 +++-- .../client-vanilla/src/resumable-upload.ts | 2 +- examples/minimal-appdir/src/app/page.tsx | 4 +- examples/minimal-pagedir/src/pages/index.tsx | 2 +- .../minimal-solidstart/src/routes/index.tsx | 2 +- .../app/routes/index.tsx | 2 +- examples/with-clerk-appdir/src/app/page.tsx | 2 +- .../with-clerk-pagesdir/src/pages/index.tsx | 2 +- .../with-drizzle-appdir/src/app/uploader.tsx | 2 +- .../with-drizzle-pagesdir/src/pages/index.tsx | 2 +- .../with-novel/uploadthing/novel-plugin.ts | 13 +++-- examples/with-tailwindcss/src/app/page.tsx | 2 +- packages/react/src/types.ts | 3 +- packages/react/src/useUploadThing.ts | 26 +++++---- packages/react/test/client-generator.test.ts | 20 ++++++- packages/react/test/upload-button.test.tsx | 20 +++++++ packages/shared/src/dropzone-utils.ts | 4 -- packages/shared/src/utils.ts | 18 ++++++ packages/shared/test/unwrap.test.ts | 57 +++++++++++++++++++ packages/solid/src/create-uploadthing.ts | 13 +++-- packages/solid/src/types.ts | 3 +- packages/svelte/src/lib/create-uploadthing.ts | 20 ++++--- packages/svelte/src/lib/types.ts | 3 +- packages/uploadthing/src/client.ts | 31 ++++++++-- packages/uploadthing/src/types.ts | 9 +++ packages/uploadthing/test/client.test.ts | 6 +- packages/vue/src/types.ts | 3 +- packages/vue/src/useUploadThing.ts | 13 +++-- 32 files changed, 329 insertions(+), 68 deletions(-) create mode 100644 .changeset/twenty-rings-unite.md create mode 100644 packages/shared/test/unwrap.test.ts diff --git a/.changeset/twenty-rings-unite.md b/.changeset/twenty-rings-unite.md new file mode 100644 index 0000000000..d76665c3f3 --- /dev/null +++ b/.changeset/twenty-rings-unite.md @@ -0,0 +1,34 @@ +--- +"uploadthing": minor +"@uploadthing/shared": minor +"@uploadthing/svelte": minor +"@uploadthing/react": minor +"@uploadthing/solid": minor +"@uploadthing/vue": minor +--- + +feat: add support to specify route endpoint that supports "Go to Definition" + +All places that accept the `endpoint` argument now additionally accept a function that gets a route registry as input and returns the endpoint to use. This allows for "Go to Definition" to go to the backend route definition directly from the component. + +### Examples + +```ts +// uploadthing/client#uploadFiles +uploadFiles( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } +) + +// uploadthing/react#useUploadThing +useUploadThing( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } +) + +// uploadthing/react#UploadButton + routeRegistry.videoAndImage} + { ... } +/> +``` \ No newline at end of file diff --git a/docs/src/app/(docs)/api-reference/client/page.mdx b/docs/src/app/(docs)/api-reference/client/page.mdx index 8b42ae83e9..48ebe7787d 100644 --- a/docs/src/app/(docs)/api-reference/client/page.mdx +++ b/docs/src/app/(docs)/api-reference/client/page.mdx @@ -40,6 +40,20 @@ const response = await uploadFiles("routeEndpoint", { The first parameter is the route endpoint to upload to, and the second parameter is an options object: + + + The endpoint arg may be a string literal or a callback function: + +```ts +await uploadFiles((routeRegistry) => routeRegistry.routeEndpoint, { ... }) +``` + +Using a callback function allows `Go to Defintion` on `routeEndpoint` to take +you straight to your backend file route definition, which is not possible when +using a string literal parameter. + + + An array of files to upload. diff --git a/docs/src/app/(docs)/api-reference/react/page.mdx b/docs/src/app/(docs)/api-reference/react/page.mdx index 635c6ce8d9..3ef615c842 100644 --- a/docs/src/app/(docs)/api-reference/react/page.mdx +++ b/docs/src/app/(docs)/api-reference/react/page.mdx @@ -212,8 +212,23 @@ export const OurUploadButton = () => ( ### Props - + The name/slug of the [route](/file-routes) you want to upload to + + + + The endpoint arg may be a string literal or a callback function: + + ```ts + await uploadFiles((routeRegistry) => routeRegistry.routeEndpoint, { ... }) + ``` + + Using a callback function allows `Go to Defintion` on `routeEndpoint` to take + you straight to your backend file route definition, which is not possible when + using a string literal parameter. + + + Input JSON data matching your validator set on the [FileRoute](/file-routes#input) @@ -353,8 +368,23 @@ export const OurUploadDropzone = () => ( ### Props - + The name/slug of the [route](/file-routes) you want to upload to upload to + + + + The endpoint arg may be a string literal or a callback function: + + ```ts + await uploadFiles((routeRegistry) => routeRegistry.routeEndpoint, { ... }) + ``` + + Using a callback function allows `Go to Defintion` on `routeEndpoint` to take + you straight to your backend file route definition, which is not possible when + using a string literal parameter. + + + Input JSON data matching your validator set on the [FileRoute](/file-routes#input) @@ -470,6 +500,20 @@ counts are allowed by the endpoint. The first parameter is the route endpoint to upload to, and the second parameter is an options object: + + +The endpoint arg may be a string literal or a callback function: + +```ts +useUploadThing((routeRegistry) => routeRegistry.routeEndpoint, { ... }) +``` + +Using a callback function allows `Go to Defintion` on `routeEndpoint` to take +you straight to your backend file route definition, which is not possible when +using a string literal parameter. + + + An array of files to upload. diff --git a/examples/backend-adapters/client-react/src/main.tsx b/examples/backend-adapters/client-react/src/main.tsx index c956205f25..cd732011db 100644 --- a/examples/backend-adapters/client-react/src/main.tsx +++ b/examples/backend-adapters/client-react/src/main.tsx @@ -24,7 +24,7 @@ function App() { }} /> routeRegistry.videoAndImage} onClientUploadComplete={(file) => { console.log("uploaded", file); alert("Upload complete"); diff --git a/examples/backend-adapters/client-vanilla/src/normal-upload.ts b/examples/backend-adapters/client-vanilla/src/normal-upload.ts index fbed7e3539..4fef87d8e4 100644 --- a/examples/backend-adapters/client-vanilla/src/normal-upload.ts +++ b/examples/backend-adapters/client-vanilla/src/normal-upload.ts @@ -37,13 +37,16 @@ export const setupUploader = (el: HTMLDivElement) => { // 👇👇👇 THIS IS THE ACTUAL UPLOAD 👇👇👇 try { - const res = await uploadFiles("videoAndImage", { - files, - signal: ac.signal, - onUploadProgress: ({ totalProgress }) => { - progressBar.value = totalProgress; + const res = await uploadFiles( + (routeRegistry) => routeRegistry.videoAndImage, + { + files, + signal: ac.signal, + onUploadProgress: ({ totalProgress }) => { + progressBar.value = totalProgress; + }, }, - }); + ); console.log("Upload complete:", res); setTimeout(() => alert(`Upload complete! ${res.length} files uploaded`)); } catch (error) { diff --git a/examples/backend-adapters/client-vanilla/src/resumable-upload.ts b/examples/backend-adapters/client-vanilla/src/resumable-upload.ts index 7494e8a696..3f9c3964a7 100644 --- a/examples/backend-adapters/client-vanilla/src/resumable-upload.ts +++ b/examples/backend-adapters/client-vanilla/src/resumable-upload.ts @@ -36,7 +36,7 @@ export const setupResumableUploader = (el: HTMLDivElement) => { // Create uploads for each file const { done, pauseUpload, resumeUpload } = await createUpload( - "videoAndImage", + (routeRegistry) => routeRegistry.videoAndImage, { files, onUploadProgress: ({ file, progress }) => { diff --git a/examples/minimal-appdir/src/app/page.tsx b/examples/minimal-appdir/src/app/page.tsx index ba9d1d9935..6a6a87c6fb 100644 --- a/examples/minimal-appdir/src/app/page.tsx +++ b/examples/minimal-appdir/src/app/page.tsx @@ -32,7 +32,7 @@ export default function Home() { /** * @see https://docs.uploadthing.com/api-reference/react#uploadbutton */ - endpoint="videoAndImage" + endpoint={(routeRegistry) => routeRegistry.videoAndImage} onClientUploadComplete={(res) => { console.log(`onClientUploadComplete`, res); alert("Upload Completed"); @@ -46,7 +46,7 @@ export default function Home() { /** * @see https://docs.uploadthing.com/api-reference/react#uploaddropzone */ - endpoint="videoAndImage" + endpoint={(routeRegistry) => routeRegistry.videoAndImage} onUploadAborted={() => { alert("Upload Aborted"); }} diff --git a/examples/minimal-pagedir/src/pages/index.tsx b/examples/minimal-pagedir/src/pages/index.tsx index 1a23e5be03..f3731bb2af 100644 --- a/examples/minimal-pagedir/src/pages/index.tsx +++ b/examples/minimal-pagedir/src/pages/index.tsx @@ -33,7 +33,7 @@ export default function Home() { /** * @see https://docs.uploadthing.com/api-reference/react#uploaddropzone */ - endpoint="videoAndImage" + endpoint={(routeRegistry) => routeRegistry.videoAndImage} onClientUploadComplete={(res) => { console.log(`onClientUploadComplete`, res); alert("Upload Completed"); diff --git a/examples/minimal-solidstart/src/routes/index.tsx b/examples/minimal-solidstart/src/routes/index.tsx index 329ca134f0..5ab4625a33 100644 --- a/examples/minimal-solidstart/src/routes/index.tsx +++ b/examples/minimal-solidstart/src/routes/index.tsx @@ -40,7 +40,7 @@ export default function Home() { /** * @see https://docs.uploadthing.com/api-reference/react#uploaddropzone */ - endpoint="videoAndImage" + endpoint={(routeRegistry) => routeRegistry.videoAndImage} onUploadBegin={(fileName) => { console.log("onUploadBegin", fileName); }} diff --git a/examples/minimal-tanstack-start/app/routes/index.tsx b/examples/minimal-tanstack-start/app/routes/index.tsx index 71dfbe11ce..1d3392dedc 100644 --- a/examples/minimal-tanstack-start/app/routes/index.tsx +++ b/examples/minimal-tanstack-start/app/routes/index.tsx @@ -50,7 +50,7 @@ function Home() { /** * @see https://docs.uploadthing.com/api-reference/react#uploaddropzone */ - endpoint="videoAndImage" + endpoint={(routeRegistry) => routeRegistry.videoAndImage} onUploadAborted={() => { alert("Upload Aborted"); }} diff --git a/examples/with-clerk-appdir/src/app/page.tsx b/examples/with-clerk-appdir/src/app/page.tsx index db89eb94c3..85561c0075 100644 --- a/examples/with-clerk-appdir/src/app/page.tsx +++ b/examples/with-clerk-appdir/src/app/page.tsx @@ -26,7 +26,7 @@ export default function Home() { /** * @see https://docs.uploadthing.com/api-reference/react#uploaddropzone */ - endpoint="videoAndImage" + endpoint={(routeRegistry) => routeRegistry.videoAndImage} onClientUploadComplete={(res) => { console.log(`onClientUploadComplete`, res); alert("Upload Completed"); diff --git a/examples/with-clerk-pagesdir/src/pages/index.tsx b/examples/with-clerk-pagesdir/src/pages/index.tsx index 6d9cada39a..42521c201a 100644 --- a/examples/with-clerk-pagesdir/src/pages/index.tsx +++ b/examples/with-clerk-pagesdir/src/pages/index.tsx @@ -27,7 +27,7 @@ export default function Home() { /** * @see https://docs.uploadthing.com/api-reference/react#uploaddropzone */ - endpoint="videoAndImage" + endpoint={(routeRegistry) => routeRegistry.videoAndImage} onClientUploadComplete={(res) => { console.log(`onClientUploadComplete`, res); alert("Upload Completed"); diff --git a/examples/with-drizzle-appdir/src/app/uploader.tsx b/examples/with-drizzle-appdir/src/app/uploader.tsx index b44689b0c4..fe23b2dccb 100644 --- a/examples/with-drizzle-appdir/src/app/uploader.tsx +++ b/examples/with-drizzle-appdir/src/app/uploader.tsx @@ -49,7 +49,7 @@ export function Uploader() { /** * @see https://docs.uploadthing.com/api-reference/react#uploaddropzone */ - endpoint="videoAndImage" + endpoint={(routeRegistry) => routeRegistry.videoAndImage} onClientUploadComplete={(res) => { console.log(`onClientUploadComplete`, res); alert("Upload Completed"); diff --git a/examples/with-drizzle-pagesdir/src/pages/index.tsx b/examples/with-drizzle-pagesdir/src/pages/index.tsx index 5097a31e40..87d05d7a67 100644 --- a/examples/with-drizzle-pagesdir/src/pages/index.tsx +++ b/examples/with-drizzle-pagesdir/src/pages/index.tsx @@ -48,7 +48,7 @@ export default function Page() { /** * @see https://docs.uploadthing.com/api-reference/react#uploaddropzone */ - endpoint="videoAndImage" + endpoint={(routeRegistry) => routeRegistry.videoAndImage} onClientUploadComplete={(res) => { console.log(`onClientUploadComplete`, res); }} diff --git a/examples/with-novel/uploadthing/novel-plugin.ts b/examples/with-novel/uploadthing/novel-plugin.ts index 3c305a3fb2..7b61dacab2 100644 --- a/examples/with-novel/uploadthing/novel-plugin.ts +++ b/examples/with-novel/uploadthing/novel-plugin.ts @@ -27,9 +27,12 @@ export const uploadFn = createImageUpload({ /** * Upload the file to the server and preload the image in the browser */ - const uploadPromise = uploadFiles("imageUploader", { - files: [file], - }); + const uploadPromise = uploadFiles( + (routeRegistry) => routeRegistry.imageUploader, + { + files: [file], + }, + ); return new Promise((resolve) => { toast.promise( @@ -47,7 +50,9 @@ export const uploadFn = createImageUpload({ }); }, validateFn: (file) => { - const config = getRouteConfig("imageUploader"); + const config = getRouteConfig( + (routeRegistry) => routeRegistry.imageUploader, + ); if (!isValidFileType(file, config)) { toast.error("File type not supported."); return false; diff --git a/examples/with-tailwindcss/src/app/page.tsx b/examples/with-tailwindcss/src/app/page.tsx index 7daca96d4d..82586c169a 100644 --- a/examples/with-tailwindcss/src/app/page.tsx +++ b/examples/with-tailwindcss/src/app/page.tsx @@ -27,7 +27,7 @@ export default function Home() { /> routeRegistry.videoAndImage} onClientUploadComplete={(res) => { console.log(`onClientUploadComplete`, res); alert("Upload Completed"); diff --git a/packages/react/src/types.ts b/packages/react/src/types.ts index 7dd60b0ba9..9465a7e3d4 100644 --- a/packages/react/src/types.ts +++ b/packages/react/src/types.ts @@ -7,6 +7,7 @@ import type { } from "@uploadthing/shared"; import type { ClientUploadedFileData, + EndpointArg, FileRouter, inferEndpointInput, inferEndpointOutput, @@ -110,7 +111,7 @@ export type UploadthingComponentProps< /** * The endpoint from your FileRouter to use for the upload */ - endpoint: TEndpoint; + endpoint: EndpointArg; /** * URL to the UploadThing API endpoint * @example URL { /api/uploadthing } diff --git a/packages/react/src/useUploadThing.ts b/packages/react/src/useUploadThing.ts index 7b7b799751..fa53cc8582 100644 --- a/packages/react/src/useUploadThing.ts +++ b/packages/react/src/useUploadThing.ts @@ -7,6 +7,7 @@ import type { import { INTERNAL_DO_NOT_USE__fatalClientError, resolveMaybeUrlArg, + unwrap, UploadAbortedError, UploadThingError, warnIfInvalidPeerDependency, @@ -16,6 +17,7 @@ import { version as uploadthingClientVersion, } from "uploadthing/client"; import type { + EndpointArg, FileRouter, inferEndpointInput, inferErrorShape, @@ -52,10 +54,10 @@ export function __useUploadThingInternal< TEndpoint extends keyof TRouter, >( url: URL, - endpoint: TEndpoint, + endpoint: EndpointArg, opts?: UseUploadthingProps, ) { - const { uploadFiles } = genUploader({ + const { uploadFiles, routeRegistry } = genUploader({ url, package: "@uploadthing/react", }); @@ -64,7 +66,7 @@ export function __useUploadThingInternal< const uploadProgress = useRef(0); const fileProgress = useRef>(new Map()); - type InferredInput = inferEndpointInput; + type InferredInput = inferEndpointInput; type FuncInput = undefined extends InferredInput ? [files: File[], input?: undefined] : [files: File[], input: InferredInput]; @@ -131,7 +133,8 @@ export function __useUploadThingInternal< } }); - const routeConfig = useRouteConfig(url, endpoint as string); + const _endpoint = unwrap(endpoint, routeRegistry); + const routeConfig = useRouteConfig(url, _endpoint as string); return { startUpload, @@ -151,15 +154,21 @@ export const generateReactHelpers = ( const url = resolveMaybeUrlArg(initOpts?.url); + const clientHelpers = genUploader({ + url, + package: "@uploadthing/react", + }); + function useUploadThing( - endpoint: TEndpoint, + endpoint: EndpointArg, opts?: UseUploadthingProps, ) { return __useUploadThingInternal(url, endpoint, opts); } - function getRouteConfig(endpoint: keyof TRouter) { + function getRouteConfig(slug: EndpointArg) { const maybeServerData = globalThis.__UPLOADTHING; + const endpoint = unwrap(slug, clientHelpers.routeRegistry); const config = maybeServerData?.find((x) => x.slug === endpoint)?.config; if (!config) { throw new Error( @@ -171,10 +180,7 @@ export const generateReactHelpers = ( return { useUploadThing, - ...genUploader({ - url, - package: "@uploadthing/react", - }), + ...clientHelpers, /** * Get the config for a given endpoint outside of React context. * @remarks Can only be used if the NextSSRPlugin is used in the app. diff --git a/packages/react/test/client-generator.test.ts b/packages/react/test/client-generator.test.ts index bf90c4285c..f655af05c0 100644 --- a/packages/react/test/client-generator.test.ts +++ b/packages/react/test/client-generator.test.ts @@ -1,4 +1,4 @@ -import { expectTypeOf, it } from "vitest"; +import { describe, expectTypeOf, it } from "vitest"; import * as z from "zod"; import { createUploadthing } from "uploadthing/server"; @@ -149,3 +149,21 @@ it("infers output properly", () => { expectTypeOf[] | undefined>(res); }); }); + +it("gets go-to-definition proxy as endpoint arg", () => { + doNotExecute(async () => { + const { startUpload } = useUploadThing( + (routeRegistry) => routeRegistry.withFooInput, + ); + type _Input = Parameters[1]; + expectTypeOf<_Input>().toEqualTypeOf<{ foo: string }>(); + }); + + doNotExecute(async () => { + const { startUpload } = useUploadThing( + (routeRegistry) => routeRegistry.exampleRoute, + ); + const res = await startUpload(files); + expectTypeOf[] | undefined>(res); + }); +}); diff --git a/packages/react/test/upload-button.test.tsx b/packages/react/test/upload-button.test.tsx index 15367cc86b..5ecfe5e41c 100644 --- a/packages/react/test/upload-button.test.tsx +++ b/packages/react/test/upload-button.test.tsx @@ -117,6 +117,26 @@ describe("UploadButton - basic", () => { expect(utils.getByText("Image (4MB)")).toBeInTheDocument(); }); + it("fetches and displays route config (with callback endpoint arg)", async () => { + const utils = render( + routeRegistry.image} />, + ); + const label = utils.container.querySelector("label"); + + if (!label) throw new Error("No label found"); + + // Previously, when component was disabled, it would show "Loading..." + // expect(label).toHaveTextContent("Loading..."); + + // then eventually we load in the data, and we should be in the ready state + await waitFor(() => expect(label).toHaveAttribute("data-state", "ready")); + expect(label).toHaveTextContent("Choose File"); + expect(label).not.toHaveTextContent("(s)"); + + expect(utGet).toHaveBeenCalledOnce(); + expect(utils.getByText("Image (4MB)")).toBeInTheDocument(); + }); + it("shows plural when maxFileCount is > 1", async () => { const utils = render(); const label = utils.container.querySelector("label"); diff --git a/packages/shared/src/dropzone-utils.ts b/packages/shared/src/dropzone-utils.ts index 9cc5ff3d47..b4341e6bbb 100644 --- a/packages/shared/src/dropzone-utils.ts +++ b/packages/shared/src/dropzone-utils.ts @@ -167,10 +167,6 @@ export function acceptPropAsAcceptAttr(accept?: AcceptProp) { return undefined; } -export function noop() { - // noop -} - /** * ================================================ * Reducer diff --git a/packages/shared/src/utils.ts b/packages/shared/src/utils.ts index 6f4f2e05d3..c7d5e2feb8 100644 --- a/packages/shared/src/utils.ts +++ b/packages/shared/src/utils.ts @@ -17,6 +17,7 @@ import type { FileRouterInputConfig, FileRouterInputKey, FileSize, + Json, ResponseEsque, RouteConfig, Time, @@ -351,3 +352,20 @@ export const safeNumberReplacer = (_: string, value: unknown) => { if (value === -Infinity) return Number.MIN_SAFE_INTEGER; if (Number.isNaN(value)) return 0; }; + +export function noop() { + // noop +} + +export function createIdentityProxy>() { + return new Proxy(noop, { + get: (_, prop) => prop, + }) as unknown as TObj; +} + +export function unwrap( + x: T | ((...args: Param) => T), + ...args: Param +) { + return typeof x === "function" ? x(...args) : x; +} diff --git a/packages/shared/test/unwrap.test.ts b/packages/shared/test/unwrap.test.ts new file mode 100644 index 0000000000..ade41cedb1 --- /dev/null +++ b/packages/shared/test/unwrap.test.ts @@ -0,0 +1,57 @@ +import { describe, expect, expectTypeOf, it } from "vitest"; + +import { unwrap } from "../src/utils"; + +describe("unwrap", () => { + it("value", () => { + const value = unwrap(1); + expectTypeOf(value); + expect(value).toBe(1); + }); + + it("function w/ no args", () => { + const getter = () => 1; + const value = unwrap(getter); + expectTypeOf(value); + expect(value).toBe(1); + }); + + it("function w/ 1 arg", () => { + const getter = (x: number) => x; + const value = unwrap(getter, 1); + expectTypeOf(value); + expect(value).toBe(1); + + { + // @ts-expect-error - missing args + unwrap(getter); + // @ts-expect-error - invalid args + unwrap(getter, 1, 2); + // @ts-expect-error - invalid args + unwrap(getter, "1"); + } + }); + + it("function w/ 2 args", () => { + const getter = (x: number, y: number) => x + y; + const value = unwrap(getter, 1, 2); + expectTypeOf(value); + expect(value).toBe(3); + }); + + it("function w/ many different args", () => { + const getter = (x: number, s: string, opts?: { y: number }) => { + return x + s.length + (opts?.y ?? 0); + }; + { + const value = unwrap(getter, 1, "foo", { y: 2 }); + expectTypeOf(value); + expect(value).toBe(6); + } + { + const value = unwrap(getter, 1, "foo"); + expectTypeOf(value); + expect(value).toBe(4); + } + }); +}); diff --git a/packages/solid/src/create-uploadthing.ts b/packages/solid/src/create-uploadthing.ts index 812a01119e..859bc2c53d 100644 --- a/packages/solid/src/create-uploadthing.ts +++ b/packages/solid/src/create-uploadthing.ts @@ -3,12 +3,14 @@ import { createSignal } from "solid-js"; import { INTERNAL_DO_NOT_USE__fatalClientError, resolveMaybeUrlArg, + unwrap, UploadAbortedError, UploadThingError, } from "@uploadthing/shared"; import type { EndpointMetadata } from "@uploadthing/shared"; import { genUploader } from "uploadthing/client"; import type { + EndpointArg, FileRouter, inferEndpointInput, inferErrorShape, @@ -35,20 +37,20 @@ export const INTERNAL_createUploadThingGen = < */ url: URL; }) => { - const { uploadFiles } = genUploader({ + const { uploadFiles, routeRegistry } = genUploader({ url: initOpts.url, package: "@uploadthing/solid", }); const createUploadThing = ( - endpoint: TEndpoint, + endpoint: EndpointArg, opts?: CreateUploadthingProps, ) => { const [isUploading, setUploading] = createSignal(false); let uploadProgress = 0; let fileProgress = new Map(); - type InferredInput = inferEndpointInput; + type InferredInput = inferEndpointInput; type FuncInput = undefined extends InferredInput ? [files: File[], input?: undefined] : [files: File[], input: InferredInput]; @@ -116,7 +118,8 @@ export const INTERNAL_createUploadThingGen = < } }; - const routeConfig = createRouteConfig(initOpts.url, endpoint as string); + const _endpoint = unwrap(endpoint, routeRegistry); + const routeConfig = createRouteConfig(initOpts.url, _endpoint as string); return { startUpload, @@ -126,7 +129,7 @@ export const INTERNAL_createUploadThingGen = < * @deprecated Use `routeConfig` instead */ permittedFileInfo: routeConfig - ? { slug: endpoint, config: routeConfig } + ? { slug: _endpoint, config: routeConfig } : undefined, } as const; }; diff --git a/packages/solid/src/types.ts b/packages/solid/src/types.ts index c9cc565bee..4c8e4ba2d9 100644 --- a/packages/solid/src/types.ts +++ b/packages/solid/src/types.ts @@ -7,6 +7,7 @@ import type { } from "@uploadthing/shared"; import type { ClientUploadedFileData, + EndpointArg, FileRouter, inferEndpointInput, inferEndpointOutput, @@ -119,7 +120,7 @@ export type UploadthingComponentProps< /** * The endpoint from your FileRouter to use for the upload */ - endpoint: TEndpoint; + endpoint: EndpointArg; /** * URL to the UploadThing API endpoint * @example "/api/uploadthing" diff --git a/packages/svelte/src/lib/create-uploadthing.ts b/packages/svelte/src/lib/create-uploadthing.ts index 75fa19b1ca..7b7489798e 100644 --- a/packages/svelte/src/lib/create-uploadthing.ts +++ b/packages/svelte/src/lib/create-uploadthing.ts @@ -4,12 +4,17 @@ import type { EndpointMetadata } from "@uploadthing/shared"; import { INTERNAL_DO_NOT_USE__fatalClientError, resolveMaybeUrlArg, + unwrap, UploadAbortedError, UploadThingError, } from "@uploadthing/shared"; import { genUploader } from "uploadthing/client"; import type { FileRouter } from "uploadthing/server"; -import type { inferEndpointInput, inferErrorShape } from "uploadthing/types"; +import type { + EndpointArg, + inferEndpointInput, + inferErrorShape, +} from "uploadthing/types"; import type { GenerateTypedHelpersOptions, @@ -36,20 +41,20 @@ export const INTERNAL_createUploadThingGen = < */ url: URL; }) => { - const { uploadFiles } = genUploader({ + const { uploadFiles, routeRegistry } = genUploader({ url: initOpts.url, package: "@uploadthing/svelte", }); const useUploadThing = ( - endpoint: TEndpoint, + endpoint: EndpointArg, opts?: UseUploadthingProps, ) => { const isUploading = writable(false); let uploadProgress = 0; let fileProgress = new Map(); - type InferredInput = inferEndpointInput; + type InferredInput = inferEndpointInput; type FuncInput = undefined extends InferredInput ? [files: File[], input?: undefined] : [files: File[], input: InferredInput]; @@ -116,7 +121,8 @@ export const INTERNAL_createUploadThingGen = < } }; - const routeConfig = createRouteConfig(initOpts.url, endpoint as string); + const _endpoint = unwrap(endpoint, routeRegistry); + const routeConfig = createRouteConfig(initOpts.url, _endpoint as string); return { startUpload, @@ -126,7 +132,7 @@ export const INTERNAL_createUploadThingGen = < * @deprecated Use `routeConfig` instead */ permittedFileInfo: routeConfig - ? { slug: endpoint, config: readonly(routeConfig) } + ? { slug: _endpoint, config: readonly(routeConfig) } : undefined, } as const; }; @@ -135,7 +141,7 @@ export const INTERNAL_createUploadThingGen = < const generateUploader = () => { return ( - endpoint: TEndpoint, + endpoint: EndpointArg, props: Omit, "endpoint">, ) => ({ endpoint, ...props }); }; diff --git a/packages/svelte/src/lib/types.ts b/packages/svelte/src/lib/types.ts index 5d2314a104..fe59cae3dd 100644 --- a/packages/svelte/src/lib/types.ts +++ b/packages/svelte/src/lib/types.ts @@ -7,6 +7,7 @@ import type { } from "@uploadthing/shared"; import type { ClientUploadedFileData, + EndpointArg, FileRouter, inferEndpointInput, inferEndpointOutput, @@ -110,7 +111,7 @@ export type UploadthingComponentProps< /** * The endpoint from your FileRouter to use for the upload */ - endpoint: TEndpoint; + endpoint: EndpointArg; /** * URL to the UploadThing API endpoint * @example URL { /api/uploadthing } diff --git a/packages/uploadthing/src/client.ts b/packages/uploadthing/src/client.ts index 1799988bd2..23d381361b 100644 --- a/packages/uploadthing/src/client.ts +++ b/packages/uploadthing/src/client.ts @@ -3,6 +3,7 @@ import * as Micro from "effect/Micro"; import type { ExpandedRouteConfig } from "@uploadthing/shared"; import { asArray, + createIdentityProxy, FetchContext, fileSizeToBytes, matchFileType, @@ -21,9 +22,11 @@ import { createUTReporter } from "./internal/ut-reporter"; import type { ClientUploadedFileData, CreateUploadOptions, + EndpointArg, GenerateUploaderOptions, inferEndpointInput, NewPresignedUrl, + RouteRegistry, UploadFilesOptions, } from "./types"; @@ -80,11 +83,13 @@ export const isValidFileSize = ( export const genUploader = ( initOpts: GenerateUploaderOptions, ) => { + const routeRegistry = createIdentityProxy>(); + const controllableUpload = async < TEndpoint extends keyof TRouter, TServerOutput = inferEndpointOutput, >( - slug: TEndpoint, + slug: EndpointArg, opts: Omit< CreateUploadOptions, keyof GenerateUploaderOptions @@ -98,8 +103,10 @@ export const genUploader = ( } >(); + const endpoint = typeof slug === "function" ? slug(routeRegistry) : slug; + const utReporter = createUTReporter({ - endpoint: String(slug), + endpoint: String(endpoint), package: initOpts.package, url: resolveMaybeUrlArg(initOpts?.url), headers: opts.headers, @@ -239,13 +246,15 @@ export const genUploader = ( * and then uploads the files to UploadThing */ const typedUploadFiles = ( - endpoint: TEndpoint, + slug: EndpointArg, opts: Omit< UploadFilesOptions, keyof GenerateUploaderOptions >, - ) => - uploadFilesInternal(endpoint, { + ) => { + const endpoint = typeof slug === "function" ? slug(routeRegistry) : slug; + + return uploadFilesInternal(endpoint, { ...opts, skipPolling: {} as never, // Remove in a future version, it's type right not is an ErrorMessage to help migrations. url: resolveMaybeUrlArg(initOpts?.url), @@ -264,6 +273,16 @@ export const genUploader = ( } throw Micro.causeSquash(exit.left); }); + }; - return { uploadFiles: typedUploadFiles, createUpload: controllableUpload }; + return { + uploadFiles: typedUploadFiles, + createUpload: controllableUpload, + /** + * Identity object that can be used instead of raw strings + * that allows "Go to definition" in your IDE to bring you + * to the backend definition of a route. + */ + routeRegistry, + }; }; diff --git a/packages/uploadthing/src/types.ts b/packages/uploadthing/src/types.ts index cbd73057a2..84bf04b457 100644 --- a/packages/uploadthing/src/types.ts +++ b/packages/uploadthing/src/types.ts @@ -159,3 +159,12 @@ export type GenerateUploaderOptions = { */ package: string; }; + +export type EndpointArg< + TRouter extends FileRouter, + TEndpoint extends keyof TRouter, +> = TEndpoint | ((_: RouteRegistry) => TEndpoint); + +export type RouteRegistry = { + [k in keyof TRouter]: k; +}; diff --git a/packages/uploadthing/test/client.test.ts b/packages/uploadthing/test/client.test.ts index 5e3e189192..748a876f17 100644 --- a/packages/uploadthing/test/client.test.ts +++ b/packages/uploadthing/test/client.test.ts @@ -121,7 +121,9 @@ describe("uploadFiles", () => { const { uploadFiles, close } = await setupUTServer(); const file = new File(["foo"], "foo.txt", { type: "text/plain" }); - await expect(uploadFiles("foo", { files: [file] })).resolves.toEqual([ + await expect( + uploadFiles((routeRegistry) => routeRegistry.foo, { files: [file] }), + ).resolves.toEqual([ { name: "foo.txt", size: 3, @@ -161,7 +163,7 @@ describe("uploadFiles", () => { const file = new File(["foo"], "foo.txt", { type: "text/plain" }); await expect( - uploadFiles("foo", { + uploadFiles((routeRegistry) => routeRegistry.foo, { files: [file], headers: { authorization: "Bearer my-auth-token", diff --git a/packages/vue/src/types.ts b/packages/vue/src/types.ts index ab14ec1712..2af9727089 100644 --- a/packages/vue/src/types.ts +++ b/packages/vue/src/types.ts @@ -7,6 +7,7 @@ import type { } from "@uploadthing/shared"; import type { ClientUploadedFileData, + EndpointArg, FileRouter, inferEndpointInput, inferEndpointOutput, @@ -110,7 +111,7 @@ export type UploadthingComponentProps< /** * The endpoint from your FileRouter to use for the upload */ - endpoint: TEndpoint; + endpoint: EndpointArg; config?: { mode?: "auto" | "manual"; appendOnPaste?: boolean; diff --git a/packages/vue/src/useUploadThing.ts b/packages/vue/src/useUploadThing.ts index c4810df8f9..949ce66af4 100644 --- a/packages/vue/src/useUploadThing.ts +++ b/packages/vue/src/useUploadThing.ts @@ -5,11 +5,13 @@ import type { EndpointMetadata } from "@uploadthing/shared"; import { INTERNAL_DO_NOT_USE__fatalClientError, resolveMaybeUrlArg, + unwrap, UploadAbortedError, UploadThingError, } from "@uploadthing/shared"; import { genUploader } from "uploadthing/client"; import type { + EndpointArg, FileRouter, inferEndpointInput, inferErrorShape, @@ -46,20 +48,20 @@ export const INTERNAL_uploadthingHookGen = < */ url: URL; }) => { - const { uploadFiles } = genUploader({ + const { uploadFiles, routeRegistry } = genUploader({ url: initOpts.url, package: "@uploadthing/vue", }); const useUploadThing = ( - endpoint: TEndpoint, + endpoint: EndpointArg, opts?: UseUploadthingProps, ) => { const isUploading = ref(false); const uploadProgress = ref(0); const fileProgress = ref(new Map()); - type InferredInput = inferEndpointInput; + type InferredInput = inferEndpointInput; type FuncInput = undefined extends InferredInput ? [files: File[], input?: undefined] : [files: File[], input: InferredInput]; @@ -126,7 +128,8 @@ export const INTERNAL_uploadthingHookGen = < } }); - const routeConfig = useRouteConfig(initOpts.url, endpoint as string); + const _endpoint = computed(() => unwrap(endpoint, routeRegistry)); + const routeConfig = useRouteConfig(initOpts.url, _endpoint.value as string); return { startUpload, @@ -136,7 +139,7 @@ export const INTERNAL_uploadthingHookGen = < * @deprecated Use `routeConfig` instead */ permittedFileInfo: routeConfig - ? { slug: endpoint, config: routeConfig } + ? { slug: _endpoint.value, config: routeConfig } : undefined, } as const; }; From 176b2e9ed98a3e802182d95e34adbfcfe667d120 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 24 Oct 2024 12:11:13 +0200 Subject: [PATCH 04/15] chore: update svelte peer dep range (#1029) --- .changeset/flat-seals-change.md | 5 +++++ packages/svelte/package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/flat-seals-change.md diff --git a/.changeset/flat-seals-change.md b/.changeset/flat-seals-change.md new file mode 100644 index 0000000000..90a853522b --- /dev/null +++ b/.changeset/flat-seals-change.md @@ -0,0 +1,5 @@ +--- +"@uploadthing/svelte": patch +--- + +chore: update svelte peer dep range diff --git a/packages/svelte/package.json b/packages/svelte/package.json index c777ec230a..4ff2114ae9 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -29,7 +29,7 @@ "!dist/**/*.spec.*" ], "peerDependencies": { - "svelte": "^4.0.0 || ^5.0.0-next.0", + "svelte": "^4.0.0 || ^5.0.0", "uploadthing": "^7.0.0" }, "dependencies": { From 72ac25044f14d2c0b5c5b870b9bb4218c766abf2 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 24 Oct 2024 12:11:39 +0200 Subject: [PATCH 05/15] feat: add `effect/Redacted` (#993) --- .changeset/orange-roses-sip.md | 6 + examples/backend-adapters/server/package.json | 7 +- package.json | 2 +- packages/shared/package.json | 2 +- packages/shared/src/crypto.ts | 14 ++- packages/shared/test/crypto.test.ts | 18 +-- packages/uploadthing/package.json | 5 +- .../uploadthing/src/internal/config.test.ts | 7 +- packages/uploadthing/src/internal/config.ts | 2 +- packages/uploadthing/src/internal/handler.ts | 7 +- .../uploadthing/src/internal/jsonl.test.ts | 4 +- packages/uploadthing/src/internal/jsonl.ts | 2 +- .../uploadthing/src/internal/route-config.ts | 2 +- packages/uploadthing/src/internal/runtime.ts | 17 ++- .../src/internal/shared-schemas.ts | 4 +- packages/uploadthing/src/internal/types.ts | 2 +- packages/uploadthing/src/sdk/index.ts | 5 +- packages/uploadthing/test/__test-helpers.ts | 5 +- .../uploadthing/test/request-handler.test.ts | 3 +- packages/uploadthing/test/sdk.test.ts | 2 +- pnpm-lock.yaml | 104 ++++++++---------- 21 files changed, 118 insertions(+), 102 deletions(-) create mode 100644 .changeset/orange-roses-sip.md diff --git a/.changeset/orange-roses-sip.md b/.changeset/orange-roses-sip.md new file mode 100644 index 0000000000..47bd9655c4 --- /dev/null +++ b/.changeset/orange-roses-sip.md @@ -0,0 +1,6 @@ +--- +"@uploadthing/shared": patch +"uploadthing": patch +--- + +chore: redact sensitive fields from logs using `effect/Redacted` diff --git a/examples/backend-adapters/server/package.json b/examples/backend-adapters/server/package.json index fc6bfb1a21..669e2e949d 100644 --- a/examples/backend-adapters/server/package.json +++ b/examples/backend-adapters/server/package.json @@ -12,15 +12,14 @@ "dev:effect": "NODE_ENV=development PORT=3003 tsx watch src/effect-platform.ts" }, "dependencies": { - "@effect/platform": "0.68.5", - "@effect/platform-node": "0.63.5", - "@effect/schema": "0.75.4", + "@effect/platform": "0.69.6", + "@effect/platform-node": "0.64.7", "@elysiajs/cors": "^1.1.1", "@fastify/cors": "^9.0.1", "@hono/node-server": "^1.8.2", "cors": "^2.8.5", "dotenv": "^16.4.5", - "effect": "3.9.2", + "effect": "3.10.2", "elysia": "^1.1.16", "express": "^4.18.2", "fastify": "^4.26.1", diff --git a/package.json b/package.json index 0da7643044..245bfe78b1 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@actions/github": "^6.0.0", "@changesets/changelog-github": "^0.5.0", "@changesets/cli": "^2.27.1", - "@effect/vitest": "0.12.1", + "@effect/vitest": "0.13.1", "@ianvs/prettier-plugin-sort-imports": "^4.2.1", "@manypkg/cli": "^0.21.3", "@playwright/test": "1.45.0", diff --git a/packages/shared/package.json b/packages/shared/package.json index f3ce7f7317..3c0c0fbbdb 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -36,7 +36,7 @@ }, "dependencies": { "@uploadthing/mime-types": "workspace:*", - "effect": "3.9.2", + "effect": "3.10.2", "sqids": "^0.3.0" }, "devDependencies": { diff --git a/packages/shared/src/crypto.ts b/packages/shared/src/crypto.ts index 2d4634132f..2d771a9cd0 100644 --- a/packages/shared/src/crypto.ts +++ b/packages/shared/src/crypto.ts @@ -1,6 +1,7 @@ import * as Encoding from "effect/Encoding"; import * as Hash from "effect/Hash"; import * as Micro from "effect/Micro"; +import * as Redacted from "effect/Redacted"; import SQIds, { defaultOptions } from "sqids"; import { UploadThingError } from "./error"; @@ -27,13 +28,16 @@ function shuffle(str: string, seed: string) { return chars.join(""); } -export const signPayload = (payload: string, secret: string) => +export const signPayload = ( + payload: string, + secret: Redacted.Redacted, +) => Micro.gen(function* () { const signingKey = yield* Micro.tryPromise({ try: () => crypto.subtle.importKey( "raw", - encoder.encode(secret), + encoder.encode(Redacted.value(secret)), algorithm, false, ["sign"], @@ -61,13 +65,13 @@ export const signPayload = (payload: string, secret: string) => export const verifySignature = ( payload: string, signature: string | null, - secret: string, + secret: Redacted.Redacted, ) => Micro.gen(function* () { const sig = signature?.slice(signaturePrefix.length); if (!sig) return false; - const secretBytes = encoder.encode(secret); + const secretBytes = encoder.encode(Redacted.value(secret)); const signingKey = yield* Micro.promise(() => crypto.subtle.importKey("raw", secretBytes, algorithm, false, ["verify"]), ); @@ -131,7 +135,7 @@ export const verifyKey = (key: string, appId: string) => export const generateSignedURL = ( url: string | URL, - secretKey: string, + secretKey: Redacted.Redacted, opts: { ttlInSeconds?: Time | undefined; data?: Record; diff --git a/packages/shared/test/crypto.test.ts b/packages/shared/test/crypto.test.ts index a9ec8cc137..02ff9a6945 100644 --- a/packages/shared/test/crypto.test.ts +++ b/packages/shared/test/crypto.test.ts @@ -1,6 +1,6 @@ import { it } from "@effect/vitest"; import * as Effect from "effect/Effect"; -import * as Exit from "effect/Exit"; +import * as Redacted from "effect/Redacted"; import { describe, expect } from "vitest"; import { @@ -14,7 +14,7 @@ import { describe("crypto sign / verify", () => { it.effect("signs and verifies a payload", () => Effect.gen(function* () { - const secret = "foo-123"; + const secret = Redacted.make("foo-123"); const payload = "hello world"; const sig = yield* signPayload(payload, secret); @@ -26,7 +26,7 @@ describe("crypto sign / verify", () => { it.effect("doesn't verify a payload with a bad signature", () => Effect.gen(function* () { - const secret = "foo-123"; + const secret = Redacted.make("foo-123"); const payload = "hello world"; const sig = yield* signPayload(payload, secret); @@ -38,11 +38,15 @@ describe("crypto sign / verify", () => { it.effect("doesn't verify a payload with a bad secret", () => Effect.gen(function* () { - const secret = "foo-123"; + const secret = Redacted.make("foo-123"); const payload = "hello world"; const sig = yield* signPayload(payload, secret); - const verified = yield* verifySignature(payload, sig, "bad"); + const verified = yield* verifySignature( + payload, + sig, + Redacted.make("bad"), + ); expect(verified).toBe(false); }), @@ -51,7 +55,7 @@ describe("crypto sign / verify", () => { it.effect("generates a signed URL", () => Effect.gen(function* () { const url = "https://example.com"; - const secret = "foo-123"; + const secret = Redacted.make("foo-123"); const signedURL = yield* generateSignedURL(url, secret, { ttlInSeconds: 60 * 60, @@ -67,7 +71,7 @@ describe("crypto sign / verify", () => { it.effect("generates and verifies a signed URL", () => Effect.gen(function* () { const url = "https://example.com"; - const secret = "foo-123"; + const secret = Redacted.make("foo-123"); const signedURL = yield* generateSignedURL(url, secret, { ttlInSeconds: 60 * 60, diff --git a/packages/uploadthing/package.json b/packages/uploadthing/package.json index 1c6628f4a1..2ab099a5c7 100644 --- a/packages/uploadthing/package.json +++ b/packages/uploadthing/package.json @@ -150,11 +150,10 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@effect/platform": "0.68.5", - "@effect/schema": "0.75.4", + "@effect/platform": "0.69.6", "@uploadthing/mime-types": "workspace:*", "@uploadthing/shared": "workspace:*", - "effect": "3.9.2" + "effect": "3.10.2" }, "devDependencies": { "@remix-run/server-runtime": "^2.12.0", diff --git a/packages/uploadthing/src/internal/config.test.ts b/packages/uploadthing/src/internal/config.test.ts index edf39c24ad..70eeeda818 100644 --- a/packages/uploadthing/src/internal/config.test.ts +++ b/packages/uploadthing/src/internal/config.test.ts @@ -1,9 +1,10 @@ import { after } from "node:test"; -import * as S from "@effect/schema/Schema"; import { it } from "@effect/vitest"; import * as Effect from "effect/Effect"; import * as Exit from "effect/Exit"; import * as Layer from "effect/Layer"; +import * as Redacted from "effect/Redacted"; +import * as S from "effect/Schema"; import { afterEach, beforeEach, describe, expect } from "vitest"; import { UploadThingError } from "@uploadthing/shared"; @@ -12,12 +13,12 @@ import { configProvider, IngestUrl, IsDevelopment, UTToken } from "./config"; import { ParsedToken, UploadThingToken } from "./shared-schemas"; const app1TokenData = { - apiKey: "sk_foo", + apiKey: Redacted.make("sk_foo"), appId: "app-1", regions: ["fra1"] as const, }; const app2TokenData = { - apiKey: "sk_bar", + apiKey: Redacted.make("sk_bar"), appId: "app-2", regions: ["dub1"] as const, }; diff --git a/packages/uploadthing/src/internal/config.ts b/packages/uploadthing/src/internal/config.ts index 6a77d311c1..73a5b0b74e 100644 --- a/packages/uploadthing/src/internal/config.ts +++ b/packages/uploadthing/src/internal/config.ts @@ -1,7 +1,7 @@ -import * as S from "@effect/schema/Schema"; import * as Config from "effect/Config"; import * as ConfigProvider from "effect/ConfigProvider"; import * as Effect from "effect/Effect"; +import * as S from "effect/Schema"; import { filterDefinedObjectValues, diff --git a/packages/uploadthing/src/internal/handler.ts b/packages/uploadthing/src/internal/handler.ts index 95a130cd71..c43ea03f97 100644 --- a/packages/uploadthing/src/internal/handler.ts +++ b/packages/uploadthing/src/internal/handler.ts @@ -8,11 +8,12 @@ import { HttpServerRequest, HttpServerResponse, } from "@effect/platform"; -import * as S from "@effect/schema/Schema"; import * as Config from "effect/Config"; import * as Context from "effect/Context"; import * as Effect from "effect/Effect"; import * as Match from "effect/Match"; +import * as Redacted from "effect/Redacted"; +import * as S from "effect/Schema"; import { fillInputRouteConfig, @@ -367,7 +368,7 @@ const handleCallbackRequest = (opts: { yield* HttpClientRequest.post(`/callback-result`).pipe( HttpClientRequest.prependUrl(baseUrl), HttpClientRequest.setHeaders({ - "x-uploadthing-api-key": apiKey, + "x-uploadthing-api-key": Redacted.value(apiKey), "x-uploadthing-version": pkgJson.version, "x-uploadthing-be-adapter": beAdapter, "x-uploadthing-fe-package": fePackage, @@ -594,7 +595,7 @@ const handleUploadAction = (opts: { const metadataRequest = HttpClientRequest.post("/route-metadata").pipe( HttpClientRequest.prependUrl(ingestUrl), HttpClientRequest.setHeaders({ - "x-uploadthing-api-key": apiKey, + "x-uploadthing-api-key": Redacted.value(apiKey), "x-uploadthing-version": pkgJson.version, "x-uploadthing-be-adapter": beAdapter, "x-uploadthing-fe-package": fePackage, diff --git a/packages/uploadthing/src/internal/jsonl.test.ts b/packages/uploadthing/src/internal/jsonl.test.ts index d08cab74e6..05d0cad5a7 100644 --- a/packages/uploadthing/src/internal/jsonl.test.ts +++ b/packages/uploadthing/src/internal/jsonl.test.ts @@ -1,6 +1,7 @@ import { it } from "@effect/vitest"; import * as Effect from "effect/Effect"; import * as Exit from "effect/Exit"; +import * as Redacted from "effect/Redacted"; import * as Stream from "effect/Stream"; import { beforeEach, describe, expect, vi } from "vitest"; @@ -13,7 +14,8 @@ const te = new TextEncoder(); const createChunk = (_payload: unknown) => { const payload = JSON.stringify(_payload); - return Effect.map(signPayload(payload, "sk_123"), (signature) => + const secret = Redacted.make("sk_123"); + return Effect.map(signPayload(payload, secret), (signature) => JSON.stringify( MetadataFetchStreamPart.make({ payload, signature, hook: "callback" }), ), diff --git a/packages/uploadthing/src/internal/jsonl.ts b/packages/uploadthing/src/internal/jsonl.ts index 99d8582fe6..5a75693b4d 100644 --- a/packages/uploadthing/src/internal/jsonl.ts +++ b/packages/uploadthing/src/internal/jsonl.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema"; import * as Effect from "effect/Effect"; +import * as S from "effect/Schema"; import * as Stream from "effect/Stream"; export const handleJsonLineStream = diff --git a/packages/uploadthing/src/internal/route-config.ts b/packages/uploadthing/src/internal/route-config.ts index 881a68c3fb..634b23dd23 100644 --- a/packages/uploadthing/src/internal/route-config.ts +++ b/packages/uploadthing/src/internal/route-config.ts @@ -1,6 +1,6 @@ -import type * as S from "@effect/schema/Schema"; import * as Data from "effect/Data"; import * as Effect from "effect/Effect"; +import type * as S from "effect/Schema"; import type { ExpandedRouteConfig, diff --git a/packages/uploadthing/src/internal/runtime.ts b/packages/uploadthing/src/internal/runtime.ts index 6ab7bc5131..d2b5c2ebe0 100644 --- a/packages/uploadthing/src/internal/runtime.ts +++ b/packages/uploadthing/src/internal/runtime.ts @@ -1,4 +1,5 @@ -import { FetchHttpClient } from "@effect/platform"; +import { FetchHttpClient, Headers } from "@effect/platform"; +import * as FiberRef from "effect/FiberRef"; import * as Layer from "effect/Layer"; import * as ManagedRuntime from "effect/ManagedRuntime"; @@ -12,8 +13,20 @@ export const makeRuntime = (fetch: FetchEsque, config: unknown) => { FetchHttpClient.layer, Layer.succeed(FetchHttpClient.Fetch, fetch as typeof globalThis.fetch), ); + + const withRedactedHeaders = Layer.effectDiscard( + FiberRef.update(Headers.currentRedactedNames, (_) => + _.concat(["x-uploadthing-api-key"]), + ), + ); + const layer = Layer.provide( - Layer.mergeAll(withLogFormat, withMinimalLogLevel, fetchHttpClient), + Layer.mergeAll( + withLogFormat, + withMinimalLogLevel, + fetchHttpClient, + withRedactedHeaders, + ), Layer.setConfigProvider(configProvider(config)), ); return ManagedRuntime.make(layer); diff --git a/packages/uploadthing/src/internal/shared-schemas.ts b/packages/uploadthing/src/internal/shared-schemas.ts index cbac8755dd..25bafdb50b 100644 --- a/packages/uploadthing/src/internal/shared-schemas.ts +++ b/packages/uploadthing/src/internal/shared-schemas.ts @@ -1,4 +1,4 @@ -import * as S from "@effect/schema/Schema"; +import * as S from "effect/Schema"; import type { Json } from "@uploadthing/shared"; import { ValidACLs, ValidContentDispositions } from "@uploadthing/shared"; @@ -28,7 +28,7 @@ const DecodeString = S.transform(S.Uint8ArrayFromSelf, S.String, { }); export const ParsedToken = S.Struct({ - apiKey: S.String.pipe(S.startsWith("sk_")), + apiKey: S.Redacted(S.String.pipe(S.startsWith("sk_"))), appId: S.String, regions: S.NonEmptyArray(S.String), ingestHost: S.String.pipe( diff --git a/packages/uploadthing/src/internal/types.ts b/packages/uploadthing/src/internal/types.ts index 3ea85d5c65..1f5a8224e6 100644 --- a/packages/uploadthing/src/internal/types.ts +++ b/packages/uploadthing/src/internal/types.ts @@ -1,6 +1,6 @@ -import type { Schema } from "@effect/schema/Schema"; import type * as Config from "effect/Config"; import type * as LogLevel from "effect/LogLevel"; +import type { Schema } from "effect/Schema"; import type { ErrorMessage, diff --git a/packages/uploadthing/src/sdk/index.ts b/packages/uploadthing/src/sdk/index.ts index 30b8e072f5..6094c6293d 100644 --- a/packages/uploadthing/src/sdk/index.ts +++ b/packages/uploadthing/src/sdk/index.ts @@ -4,11 +4,12 @@ import { HttpClientRequest, HttpClientResponse, } from "@effect/platform"; -import * as S from "@effect/schema/Schema"; import * as Arr from "effect/Array"; import * as Effect from "effect/Effect"; import type * as ManagedRuntime from "effect/ManagedRuntime"; import * as Predicate from "effect/Predicate"; +import * as Redacted from "effect/Redacted"; +import * as S from "effect/Schema"; import type { ACL, @@ -76,7 +77,7 @@ export class UTApi { HttpClientRequest.setHeaders({ "x-uploadthing-version": UPLOADTHING_VERSION, "x-uploadthing-be-adapter": "server-sdk", - "x-uploadthing-api-key": apiKey, + "x-uploadthing-api-key": Redacted.value(apiKey), }), httpClient.execute, Effect.tapBoth({ diff --git a/packages/uploadthing/test/__test-helpers.ts b/packages/uploadthing/test/__test-helpers.ts index 95dfb49d5a..99f5ef0e68 100644 --- a/packages/uploadthing/test/__test-helpers.ts +++ b/packages/uploadthing/test/__test-helpers.ts @@ -1,5 +1,6 @@ import { createHash } from "crypto"; -import * as S from "@effect/schema/Schema"; +import * as Redacted from "effect/Redacted"; +import * as S from "effect/Schema"; import type { StrictRequest } from "msw"; import { http, HttpResponse } from "msw"; import { setupServer } from "msw/node"; @@ -19,7 +20,7 @@ export const uploadCompleteMock = vi.fn(); export const onErrorMock = vi.fn(); const tokenData = { - apiKey: "sk_foo", + apiKey: Redacted.make("sk_foo"), appId: "app-1", regions: ["fra1"] as const, }; diff --git a/packages/uploadthing/test/request-handler.test.ts b/packages/uploadthing/test/request-handler.test.ts index 880f54d1fa..8fd975aa69 100644 --- a/packages/uploadthing/test/request-handler.test.ts +++ b/packages/uploadthing/test/request-handler.test.ts @@ -1,4 +1,5 @@ import * as Effect from "effect/Effect"; +import * as Redacted from "effect/Redacted"; import { describe, expect } from "vitest"; import { z } from "zod"; @@ -503,7 +504,7 @@ describe(".onUploadComplete()", () => { }), }); const signature = await Effect.runPromise( - signPayload(payload, "sk_live_badkey"), + signPayload(payload, Redacted.make("sk_live_badkey")), ); const res = await handler( diff --git a/packages/uploadthing/test/sdk.test.ts b/packages/uploadthing/test/sdk.test.ts index 61edb8d555..0ed59ed187 100644 --- a/packages/uploadthing/test/sdk.test.ts +++ b/packages/uploadthing/test/sdk.test.ts @@ -1,5 +1,5 @@ /* eslint-disable no-restricted-globals */ -import * as S from "@effect/schema/Schema"; +import * as S from "effect/Schema"; import { afterAll, beforeAll, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9ce536675a..e2443bcf96 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,8 +26,8 @@ importers: specifier: ^2.27.1 version: 2.27.1 '@effect/vitest': - specifier: 0.12.1 - version: 0.12.1(effect@3.9.2)(vitest@2.1.2(@types/node@20.16.11)(@vitest/browser@2.1.2)(happy-dom@13.10.1)(lightningcss@1.24.1)(msw@2.2.13(patch_hash=mpkjv35lscrawpqthnrnago5ai)(typescript@5.6.2))(terser@5.34.1)) + specifier: 0.13.1 + version: 0.13.1(effect@3.10.2)(vitest@2.1.2(@types/node@20.16.11)(@vitest/browser@2.1.2)(happy-dom@13.10.1)(lightningcss@1.24.1)(msw@2.2.13(patch_hash=mpkjv35lscrawpqthnrnago5ai)(typescript@5.6.2))(terser@5.34.1)) '@ianvs/prettier-plugin-sort-imports': specifier: ^4.2.1 version: 4.2.1(@vue/compiler-sfc@3.5.11)(prettier@3.3.3) @@ -345,14 +345,11 @@ importers: examples/backend-adapters/server: dependencies: '@effect/platform': - specifier: 0.68.5 - version: 0.68.5(@effect/schema@0.75.4(effect@3.9.2))(effect@3.9.2) + specifier: 0.69.6 + version: 0.69.6(effect@3.10.2) '@effect/platform-node': - specifier: 0.63.5 - version: 0.63.5(@effect/platform@0.68.5(@effect/schema@0.75.4(effect@3.9.2))(effect@3.9.2))(effect@3.9.2) - '@effect/schema': - specifier: 0.75.4 - version: 0.75.4(effect@3.9.2) + specifier: 0.64.7 + version: 0.64.7(@effect/platform@0.69.6(effect@3.10.2))(effect@3.10.2) '@elysiajs/cors': specifier: ^1.1.1 version: 1.1.1(elysia@1.1.16(@sinclair/typebox@0.27.8)(openapi-types@12.1.3)(typescript@5.6.2)) @@ -369,8 +366,8 @@ importers: specifier: ^16.4.5 version: 16.4.5 effect: - specifier: 3.9.2 - version: 3.9.2 + specifier: 3.10.2 + version: 3.10.2 elysia: specifier: ^1.1.16 version: 1.1.16(@sinclair/typebox@0.27.8)(openapi-types@12.1.3)(typescript@5.6.2) @@ -1482,8 +1479,8 @@ importers: specifier: workspace:* version: link:../mime-types effect: - specifier: 3.9.2 - version: 3.9.2 + specifier: 3.10.2 + version: 3.10.2 sqids: specifier: ^0.3.0 version: 0.3.0 @@ -1608,11 +1605,8 @@ importers: packages/uploadthing: dependencies: '@effect/platform': - specifier: 0.68.5 - version: 0.68.5(@effect/schema@0.75.4(effect@3.9.2))(effect@3.9.2) - '@effect/schema': - specifier: 0.75.4 - version: 0.75.4(effect@3.9.2) + specifier: 0.69.6 + version: 0.69.6(effect@3.10.2) '@uploadthing/mime-types': specifier: workspace:* version: link:../mime-types @@ -1620,8 +1614,8 @@ importers: specifier: workspace:* version: link:../shared effect: - specifier: 3.9.2 - version: 3.9.2 + specifier: 3.10.2 + version: 3.10.2 devDependencies: '@remix-run/server-runtime': specifier: ^2.12.0 @@ -2927,33 +2921,27 @@ packages: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} - '@effect/platform-node-shared@0.18.5': - resolution: {integrity: sha512-7x+ixL7x/q2xcY1WA2e6TED0PQrjk04NbvPuNbP9rmlJmrYRrJWTiHJ+mBLCmShBqjs645qwe7bUX0MdXtI8dg==} + '@effect/platform-node-shared@0.19.6': + resolution: {integrity: sha512-mgWeB1Td8SjfB9UacodJyIZcK7vRtdu9NCBGt9UvgRBlTWpjjdW3FgUWDHTq3uBWog0upC8o2BjDX3JRenmt5w==} peerDependencies: - '@effect/platform': ^0.68.5 - effect: ^3.9.2 + '@effect/platform': ^0.69.6 + effect: ^3.10.2 - '@effect/platform-node@0.63.5': - resolution: {integrity: sha512-sSd37p613YEsJuvG8IOa+vGBZFKdV6IpWlxzs0/S5nDar3fj8zmq4lrdtyX0JgqLdluNnuoaxrNjirjp9ye29w==} + '@effect/platform-node@0.64.7': + resolution: {integrity: sha512-a/wNZ6+NMN+X3xZ+11A/Ce0XDwyud2vkP+HtsuK8Td/Xw+VVW/UyvOVl3V2R5ytVdNxCszO9d/oSD9Y+EXP7+w==} peerDependencies: - '@effect/platform': ^0.68.5 - effect: ^3.9.2 + '@effect/platform': ^0.69.6 + effect: ^3.10.2 - '@effect/platform@0.68.5': - resolution: {integrity: sha512-r3W8c9aTlVDHz/7L+mll8ivM/sO1JXWW3GrJGsZvL6X2jdkCBUuaAtJzOw085eVRye916dUP+uiLjlLid9mMuw==} + '@effect/platform@0.69.6': + resolution: {integrity: sha512-1bFUVdWNuEAhmTkpZ4nyiVms95fVELbM+1ba1q6Rjd13eEHh7dMF/iZXO+Su3shdgx4CdNitUAO53F+nr93zdg==} peerDependencies: - '@effect/schema': ^0.75.4 - effect: ^3.9.2 + effect: ^3.10.2 - '@effect/schema@0.75.4': - resolution: {integrity: sha512-qpFOkkoCFgQz/r6FIeO2w3CxAD1O/K1n2ELA69VHHy9VDUskBnX+4zzYOGCi5yKAtgg61zueDIwouRwQ3dlhqw==} + '@effect/vitest@0.13.1': + resolution: {integrity: sha512-0Haoi17RqFKsz7MQMqaw9KmOqRkR8jbmKaVqYZeOtw2IgL8FbZHTBxNeVOF72wmXjlDphVSXGXnltn67ZuLAQg==} peerDependencies: - effect: ^3.9.2 - - '@effect/vitest@0.12.1': - resolution: {integrity: sha512-dUzg1CVgro8aeAVYeCEEMQlnx60CXxbztxH9KDG6/oLRZ/YixHWNytA9PGsC9UPYSgHAahjsn446HgQAnCpX4Q==} - peerDependencies: - effect: ^3.9.2 + effect: ^3.10.1 vitest: ^2.0.5 '@egjs/agent@2.4.3': @@ -8730,8 +8718,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - effect@3.9.2: - resolution: {integrity: sha512-1sx/v1HTWHTodXfzWxAFg+SCF+ACgpJVruaAMIh/NmDVvrUsf0x9PzpXvkgJUbQ1fMdmKYK//FqxeHSQ+Zxv/Q==} + effect@3.10.2: + resolution: {integrity: sha512-Sj73q9jwwR4t3WV6E0sw4KMhx0fAHebXavYS5rsHLrWKcf4fzhDh6IixJB6mDhT7rEax/9UsoYjzrc1p7VLwbw==} electron-to-chromium@1.5.28: resolution: {integrity: sha512-VufdJl+rzaKZoYVUijN13QcXVF5dWPZANeFTLNy+OSpHdDL5ynXTF35+60RSBbaQYB1ae723lQXHCrf4pyLsMw==} @@ -17549,18 +17537,18 @@ snapshots: '@discoveryjs/json-ext@0.5.7': {} - '@effect/platform-node-shared@0.18.5(@effect/platform@0.68.5(@effect/schema@0.75.4(effect@3.9.2))(effect@3.9.2))(effect@3.9.2)': + '@effect/platform-node-shared@0.19.6(@effect/platform@0.69.6(effect@3.10.2))(effect@3.10.2)': dependencies: - '@effect/platform': 0.68.5(@effect/schema@0.75.4(effect@3.9.2))(effect@3.9.2) + '@effect/platform': 0.69.6(effect@3.10.2) '@parcel/watcher': 2.4.1 - effect: 3.9.2 + effect: 3.10.2 multipasta: 0.2.5 - '@effect/platform-node@0.63.5(@effect/platform@0.68.5(@effect/schema@0.75.4(effect@3.9.2))(effect@3.9.2))(effect@3.9.2)': + '@effect/platform-node@0.64.7(@effect/platform@0.69.6(effect@3.10.2))(effect@3.10.2)': dependencies: - '@effect/platform': 0.68.5(@effect/schema@0.75.4(effect@3.9.2))(effect@3.9.2) - '@effect/platform-node-shared': 0.18.5(@effect/platform@0.68.5(@effect/schema@0.75.4(effect@3.9.2))(effect@3.9.2))(effect@3.9.2) - effect: 3.9.2 + '@effect/platform': 0.69.6(effect@3.10.2) + '@effect/platform-node-shared': 0.19.6(@effect/platform@0.69.6(effect@3.10.2))(effect@3.10.2) + effect: 3.10.2 mime: 3.0.0 undici: 6.19.8 ws: 8.18.0 @@ -17568,21 +17556,15 @@ snapshots: - bufferutil - utf-8-validate - '@effect/platform@0.68.5(@effect/schema@0.75.4(effect@3.9.2))(effect@3.9.2)': + '@effect/platform@0.69.6(effect@3.10.2)': dependencies: - '@effect/schema': 0.75.4(effect@3.9.2) - effect: 3.9.2 + effect: 3.10.2 find-my-way-ts: 0.1.5 multipasta: 0.2.5 - '@effect/schema@0.75.4(effect@3.9.2)': + '@effect/vitest@0.13.1(effect@3.10.2)(vitest@2.1.2(@types/node@20.16.11)(@vitest/browser@2.1.2)(happy-dom@13.10.1)(lightningcss@1.24.1)(msw@2.2.13(patch_hash=mpkjv35lscrawpqthnrnago5ai)(typescript@5.6.2))(terser@5.34.1))': dependencies: - effect: 3.9.2 - fast-check: 3.22.0 - - '@effect/vitest@0.12.1(effect@3.9.2)(vitest@2.1.2(@types/node@20.16.11)(@vitest/browser@2.1.2)(happy-dom@13.10.1)(lightningcss@1.24.1)(msw@2.2.13(patch_hash=mpkjv35lscrawpqthnrnago5ai)(typescript@5.6.2))(terser@5.34.1))': - dependencies: - effect: 3.9.2 + effect: 3.10.2 vitest: 2.1.2(@types/node@20.16.11)(@vitest/browser@2.1.2(@vitest/spy@2.1.2)(typescript@5.6.2)(vite@5.4.8(@types/node@20.16.11)(lightningcss@1.24.1)(terser@5.34.1))(vitest@2.1.2))(happy-dom@13.10.1)(lightningcss@1.24.1)(msw@2.2.13(patch_hash=mpkjv35lscrawpqthnrnago5ai)(typescript@5.6.2))(terser@5.34.1) '@egjs/agent@2.4.3': {} @@ -24992,7 +24974,9 @@ snapshots: ee-first@1.1.1: {} - effect@3.9.2: {} + effect@3.10.2: + dependencies: + fast-check: 3.22.0 electron-to-chromium@1.5.28: {} From e2df2a29a9674ebf62091ebfd87706e084e5046b Mon Sep 17 00:00:00 2001 From: Christian Bromann Date: Thu, 24 Oct 2024 06:11:55 -0400 Subject: [PATCH 06/15] fix: add application/yaml as mime type (#1022) --- .changeset/two-olives-shop.md | 5 +++++ packages/mime-types/src/application.ts | 4 ++++ 2 files changed, 9 insertions(+) create mode 100644 .changeset/two-olives-shop.md diff --git a/.changeset/two-olives-shop.md b/.changeset/two-olives-shop.md new file mode 100644 index 0000000000..e869a56a8f --- /dev/null +++ b/.changeset/two-olives-shop.md @@ -0,0 +1,5 @@ +--- +"@uploadthing/mime-types": patch +--- + +feat(@uploadthing/mime-types) add application/yaml as mime type diff --git a/packages/mime-types/src/application.ts b/packages/mime-types/src/application.ts index 1a12fa9d9d..9f17d37370 100644 --- a/packages/mime-types/src/application.ts +++ b/packages/mime-types/src/application.ts @@ -2634,6 +2634,10 @@ export const application = { source: "iana", extensions: ["mxml", "xhvml", "xvml", "xvm"], }, + "application/yaml": { + source: "iana", + extensions: ["yaml", "yml"], + }, "application/yang": { source: "iana", extensions: ["yang"], From b10fafa231f0b5b849723eeaf8ef0c1c5967f576 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 24 Oct 2024 12:17:01 +0200 Subject: [PATCH 07/15] Update twenty-rings-unite.md --- .changeset/twenty-rings-unite.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.changeset/twenty-rings-unite.md b/.changeset/twenty-rings-unite.md index d76665c3f3..c84e04ecb3 100644 --- a/.changeset/twenty-rings-unite.md +++ b/.changeset/twenty-rings-unite.md @@ -5,6 +5,8 @@ "@uploadthing/react": minor "@uploadthing/solid": minor "@uploadthing/vue": minor +"@uploadthing/nuxt": minor +"@uploadthing/expo": minor --- feat: add support to specify route endpoint that supports "Go to Definition" @@ -31,4 +33,4 @@ useUploadThing( endpoint={(routeRegistry) => routeRegistry.videoAndImage} { ... } /> -``` \ No newline at end of file +``` From 69e8a5c8254e2d1612cc7ed8e5da3a2df4246129 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Fri, 25 Oct 2024 11:26:11 +0200 Subject: [PATCH 08/15] chore: bump effect (#1030) --- examples/backend-adapters/server/package.json | 6 +- package.json | 2 +- packages/shared/package.json | 2 +- packages/shared/src/error.ts | 10 +-- packages/shared/src/utils.ts | 20 +---- packages/uploadthing/package.json | 4 +- packages/uploadthing/src/client.ts | 8 +- packages/uploadthing/src/sdk/index.ts | 22 ++--- packages/uploadthing/src/sdk/utils.ts | 6 +- pnpm-lock.yaml | 84 +++++++++---------- 10 files changed, 71 insertions(+), 93 deletions(-) diff --git a/examples/backend-adapters/server/package.json b/examples/backend-adapters/server/package.json index 669e2e949d..63a46fbb01 100644 --- a/examples/backend-adapters/server/package.json +++ b/examples/backend-adapters/server/package.json @@ -12,14 +12,14 @@ "dev:effect": "NODE_ENV=development PORT=3003 tsx watch src/effect-platform.ts" }, "dependencies": { - "@effect/platform": "0.69.6", - "@effect/platform-node": "0.64.7", + "@effect/platform": "0.69.8", + "@effect/platform-node": "0.64.9", "@elysiajs/cors": "^1.1.1", "@fastify/cors": "^9.0.1", "@hono/node-server": "^1.8.2", "cors": "^2.8.5", "dotenv": "^16.4.5", - "effect": "3.10.2", + "effect": "3.10.3", "elysia": "^1.1.16", "express": "^4.18.2", "fastify": "^4.26.1", diff --git a/package.json b/package.json index 245bfe78b1..9ca32084fe 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@actions/github": "^6.0.0", "@changesets/changelog-github": "^0.5.0", "@changesets/cli": "^2.27.1", - "@effect/vitest": "0.13.1", + "@effect/vitest": "0.13.3", "@ianvs/prettier-plugin-sort-imports": "^4.2.1", "@manypkg/cli": "^0.21.3", "@playwright/test": "1.45.0", diff --git a/packages/shared/package.json b/packages/shared/package.json index 3c0c0fbbdb..db50972bfa 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -36,7 +36,7 @@ }, "dependencies": { "@uploadthing/mime-types": "workspace:*", - "effect": "3.10.2", + "effect": "3.10.3", "sqids": "^0.3.0" }, "devDependencies": { diff --git a/packages/shared/src/error.ts b/packages/shared/src/error.ts index 8b73797631..4a81038ebd 100644 --- a/packages/shared/src/error.ts +++ b/packages/shared/src/error.ts @@ -1,7 +1,7 @@ import * as Micro from "effect/Micro"; +import * as Predicate from "effect/Predicate"; import type { Json } from "./types"; -import { isObject } from "./utils"; const ERROR_CODES = { // Generic @@ -81,14 +81,14 @@ export class UploadThingError< if (opts.cause instanceof Error) { this.cause = opts.cause; } else if ( - isObject(opts.cause) && - typeof opts.cause.status === "number" && - typeof opts.cause.statusText === "string" + Predicate.isRecord(opts.cause) && + Predicate.isNumber(opts.cause.status) && + Predicate.isString(opts.cause.statusText) ) { this.cause = new Error( `Response ${opts.cause.status} ${opts.cause.statusText}`, ); - } else if (typeof opts.cause === "string") { + } else if (Predicate.isString(opts.cause)) { this.cause = new Error(opts.cause); } else { this.cause = opts.cause; diff --git a/packages/shared/src/utils.ts b/packages/shared/src/utils.ts index c7d5e2feb8..f8f82ad8ec 100644 --- a/packages/shared/src/utils.ts +++ b/packages/shared/src/utils.ts @@ -168,17 +168,8 @@ export const bytesToFileSize = (bytes: number) => { }; export async function safeParseJSON( - input: string | ResponseEsque | Request, + input: ResponseEsque, ): Promise { - if (typeof input === "string") { - try { - return JSON.parse(input) as T; - } catch (err) { - console.error(`Error parsing JSON, got '${input}'`); - return new Error(`Error parsing JSON, got '${input}'`); - } - } - const text = await input.text(); try { return JSON.parse(text ?? "null") as T; @@ -195,15 +186,6 @@ export function objectKeys>( return Object.keys(obj) as (keyof T)[]; } -/** checks if obj is a valid, non-null object */ -export function isObject(obj: unknown): obj is Record { - return typeof obj === "object" && obj !== null && !Array.isArray(obj); -} - -export function asArray(val: T | T[]): T[] { - return Array.isArray(val) ? val : [val]; -} - export function filterDefinedObjectValues( obj: Record, ): Record { diff --git a/packages/uploadthing/package.json b/packages/uploadthing/package.json index 2ab099a5c7..50675002b6 100644 --- a/packages/uploadthing/package.json +++ b/packages/uploadthing/package.json @@ -150,10 +150,10 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@effect/platform": "0.69.6", + "@effect/platform": "0.69.8", "@uploadthing/mime-types": "workspace:*", "@uploadthing/shared": "workspace:*", - "effect": "3.10.2" + "effect": "3.10.3" }, "devDependencies": { "@remix-run/server-runtime": "^2.12.0", diff --git a/packages/uploadthing/src/client.ts b/packages/uploadthing/src/client.ts index 23d381361b..a166a60c23 100644 --- a/packages/uploadthing/src/client.ts +++ b/packages/uploadthing/src/client.ts @@ -1,8 +1,8 @@ +import * as Arr from "effect/Array"; import * as Micro from "effect/Micro"; import type { ExpandedRouteConfig } from "@uploadthing/shared"; import { - asArray, createIdentityProxy, FetchContext, fileSizeToBytes, @@ -170,7 +170,7 @@ export const genUploader = ( * @param file The file upload you want to pause. Can be omitted to pause all files */ const pauseUpload = (file?: File) => { - const files = asArray(file ?? opts.files); + const files = Arr.ensure(file ?? opts.files); for (const file of files) { const upload = uploads.get(file); if (!upload) return; @@ -189,7 +189,7 @@ export const genUploader = ( * @param file The file upload you want to resume. Can be omitted to resume all files */ const resumeUpload = (file?: File) => { - const files = asArray(file ?? opts.files); + const files = Arr.ensure(file ?? opts.files); for (const file of files) { const upload = uploads.get(file); if (!upload) throw "No upload found"; @@ -226,7 +226,7 @@ export const genUploader = ( > => { const promises = []; - const files = asArray(file ?? opts.files); + const files = Arr.ensure(file ?? opts.files); for (const file of files) { const upload = uploads.get(file); if (!upload) throw "No upload found"; diff --git a/packages/uploadthing/src/sdk/index.ts b/packages/uploadthing/src/sdk/index.ts index 6094c6293d..b56c683ae6 100644 --- a/packages/uploadthing/src/sdk/index.ts +++ b/packages/uploadthing/src/sdk/index.ts @@ -17,11 +17,7 @@ import type { MaybeUrl, SerializedUploadThingError, } from "@uploadthing/shared"; -import { - asArray, - parseTimeToSeconds, - UploadThingError, -} from "@uploadthing/shared"; +import { parseTimeToSeconds, UploadThingError } from "@uploadthing/shared"; import { ApiUrl, UPLOADTHING_VERSION, UTToken } from "../internal/config"; import { logHttpClientError, logHttpClientResponse } from "../internal/logger"; @@ -131,7 +127,7 @@ export class UTApi { const uploads = await this.executeAsync( Effect.flatMap( uploadFilesInternal({ - files: asArray(files), + files: Arr.ensure(files), contentDisposition: opts?.contentDisposition ?? "inline", acl: opts?.acl, }), @@ -177,7 +173,7 @@ export class UTApi { guardServerOnly(); const downloadErrors: Record = {}; - const arr = asArray(urls); + const arr = Arr.ensure(urls); const program = Effect.gen(function* () { const downloadedFiles = yield* downloadFiles(arr, downloadErrors).pipe( @@ -243,8 +239,8 @@ export class UTApi { this.requestUploadThing( "/v6/deleteFiles", keyType === "fileKey" - ? { fileKeys: asArray(keys) } - : { customIds: asArray(keys) }, + ? { fileKeys: Arr.ensure(keys) } + : { customIds: Arr.ensure(keys) }, DeleteFileResponse, ).pipe(Effect.withLogSpan("deleteFiles")), ); @@ -284,8 +280,8 @@ export class UTApi { this.requestUploadThing( "/v6/getFileUrl", keyType === "fileKey" - ? { fileKeys: asArray(keys) } - : { customIds: asArray(keys) }, + ? { fileKeys: Arr.ensure(keys) } + : { customIds: Arr.ensure(keys) }, GetFileUrlResponse, ).pipe(Effect.withLogSpan("getFileUrls")), ); @@ -345,7 +341,7 @@ export class UTApi { return await this.executeAsync( this.requestUploadThing( "/v6/renameFiles", - { updates: asArray(updates) }, + { updates: Arr.ensure(updates) }, RenameFileResponse, ).pipe(Effect.withLogSpan("renameFiles")), ); @@ -436,7 +432,7 @@ export class UTApi { guardServerOnly(); const { keyType = this.defaultKeyType } = opts ?? {}; - const updates = asArray(keys).map((key) => { + const updates = Arr.ensure(keys).map((key) => { return keyType === "fileKey" ? { fileKey: key, acl } : { customId: key, acl }; diff --git a/packages/uploadthing/src/sdk/utils.ts b/packages/uploadthing/src/sdk/utils.ts index f4917a28b2..8bc72aa0e5 100644 --- a/packages/uploadthing/src/sdk/utils.ts +++ b/packages/uploadthing/src/sdk/utils.ts @@ -1,10 +1,10 @@ import { HttpClient, HttpClientRequest } from "@effect/platform"; import * as Effect from "effect/Effect"; +import * as Predicate from "effect/Predicate"; import { generateKey, generateSignedURL, - isObject, UploadThingError, } from "@uploadthing/shared"; import type { @@ -81,7 +81,7 @@ export const downloadFiles = ( urls, (_url, idx) => Effect.gen(function* () { - let url = isObject(_url) ? _url.url : _url; + let url = Predicate.isRecord(_url) ? _url.url : _url; if (typeof url === "string") { // since dataurls will result in name being too long, tell the user // to use uploadFiles instead. @@ -101,7 +101,7 @@ export const downloadFiles = ( const { name = url.pathname.split("/").pop() ?? "unknown-filename", customId = undefined, - } = isObject(_url) ? _url : {}; + } = Predicate.isRecord(_url) ? _url : {}; const httpClient = (yield* HttpClient.HttpClient).pipe( HttpClient.filterStatusOk, ); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e2443bcf96..9724ae1d6c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,8 +26,8 @@ importers: specifier: ^2.27.1 version: 2.27.1 '@effect/vitest': - specifier: 0.13.1 - version: 0.13.1(effect@3.10.2)(vitest@2.1.2(@types/node@20.16.11)(@vitest/browser@2.1.2)(happy-dom@13.10.1)(lightningcss@1.24.1)(msw@2.2.13(patch_hash=mpkjv35lscrawpqthnrnago5ai)(typescript@5.6.2))(terser@5.34.1)) + specifier: 0.13.3 + version: 0.13.3(effect@3.10.3)(vitest@2.1.2(@types/node@20.16.11)(@vitest/browser@2.1.2)(happy-dom@13.10.1)(lightningcss@1.24.1)(msw@2.2.13(patch_hash=mpkjv35lscrawpqthnrnago5ai)(typescript@5.6.2))(terser@5.34.1)) '@ianvs/prettier-plugin-sort-imports': specifier: ^4.2.1 version: 4.2.1(@vue/compiler-sfc@3.5.11)(prettier@3.3.3) @@ -345,11 +345,11 @@ importers: examples/backend-adapters/server: dependencies: '@effect/platform': - specifier: 0.69.6 - version: 0.69.6(effect@3.10.2) + specifier: 0.69.8 + version: 0.69.8(effect@3.10.3) '@effect/platform-node': - specifier: 0.64.7 - version: 0.64.7(@effect/platform@0.69.6(effect@3.10.2))(effect@3.10.2) + specifier: 0.64.9 + version: 0.64.9(@effect/platform@0.69.8(effect@3.10.3))(effect@3.10.3) '@elysiajs/cors': specifier: ^1.1.1 version: 1.1.1(elysia@1.1.16(@sinclair/typebox@0.27.8)(openapi-types@12.1.3)(typescript@5.6.2)) @@ -366,8 +366,8 @@ importers: specifier: ^16.4.5 version: 16.4.5 effect: - specifier: 3.10.2 - version: 3.10.2 + specifier: 3.10.3 + version: 3.10.3 elysia: specifier: ^1.1.16 version: 1.1.16(@sinclair/typebox@0.27.8)(openapi-types@12.1.3)(typescript@5.6.2) @@ -1479,8 +1479,8 @@ importers: specifier: workspace:* version: link:../mime-types effect: - specifier: 3.10.2 - version: 3.10.2 + specifier: 3.10.3 + version: 3.10.3 sqids: specifier: ^0.3.0 version: 0.3.0 @@ -1605,8 +1605,8 @@ importers: packages/uploadthing: dependencies: '@effect/platform': - specifier: 0.69.6 - version: 0.69.6(effect@3.10.2) + specifier: 0.69.8 + version: 0.69.8(effect@3.10.3) '@uploadthing/mime-types': specifier: workspace:* version: link:../mime-types @@ -1614,8 +1614,8 @@ importers: specifier: workspace:* version: link:../shared effect: - specifier: 3.10.2 - version: 3.10.2 + specifier: 3.10.3 + version: 3.10.3 devDependencies: '@remix-run/server-runtime': specifier: ^2.12.0 @@ -2921,27 +2921,27 @@ packages: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} - '@effect/platform-node-shared@0.19.6': - resolution: {integrity: sha512-mgWeB1Td8SjfB9UacodJyIZcK7vRtdu9NCBGt9UvgRBlTWpjjdW3FgUWDHTq3uBWog0upC8o2BjDX3JRenmt5w==} + '@effect/platform-node-shared@0.19.8': + resolution: {integrity: sha512-uQZIx0x2EwEJtsSSSme7R1AQG4OxlLj4W4hZNuUJWm+FwFGpruzT8N+c736zq6cOzUEIlGhWW8JU3TTu2M0oHA==} peerDependencies: - '@effect/platform': ^0.69.6 - effect: ^3.10.2 + '@effect/platform': ^0.69.8 + effect: ^3.10.3 - '@effect/platform-node@0.64.7': - resolution: {integrity: sha512-a/wNZ6+NMN+X3xZ+11A/Ce0XDwyud2vkP+HtsuK8Td/Xw+VVW/UyvOVl3V2R5ytVdNxCszO9d/oSD9Y+EXP7+w==} + '@effect/platform-node@0.64.9': + resolution: {integrity: sha512-nMmdZuFCoKm69ZgIEAApo6Z+yAj7AzIp7UqNKhksYwdsYjl918R+0kHCJ7J1rl+9W8vVhCuNmU1Q2+3u1kpq4Q==} peerDependencies: - '@effect/platform': ^0.69.6 - effect: ^3.10.2 + '@effect/platform': ^0.69.8 + effect: ^3.10.3 - '@effect/platform@0.69.6': - resolution: {integrity: sha512-1bFUVdWNuEAhmTkpZ4nyiVms95fVELbM+1ba1q6Rjd13eEHh7dMF/iZXO+Su3shdgx4CdNitUAO53F+nr93zdg==} + '@effect/platform@0.69.8': + resolution: {integrity: sha512-zhBhg0c1MHMMo+grOc/6wC2/3UETLroruwrYNZ89uDtXl6EOcP5alFP+vW3NToKDA2o0hRh22KNqq4aixA7xXg==} peerDependencies: - effect: ^3.10.2 + effect: ^3.10.3 - '@effect/vitest@0.13.1': - resolution: {integrity: sha512-0Haoi17RqFKsz7MQMqaw9KmOqRkR8jbmKaVqYZeOtw2IgL8FbZHTBxNeVOF72wmXjlDphVSXGXnltn67ZuLAQg==} + '@effect/vitest@0.13.3': + resolution: {integrity: sha512-WdWB0eN4092I6yIU7w97x/6dGJZkoF0IN2evUzNQ7bTrn9A3AogeIh/qRafcoBbEaMBS9kYj/dPO5mJHcX+FGw==} peerDependencies: - effect: ^3.10.1 + effect: ^3.10.3 vitest: ^2.0.5 '@egjs/agent@2.4.3': @@ -8718,8 +8718,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - effect@3.10.2: - resolution: {integrity: sha512-Sj73q9jwwR4t3WV6E0sw4KMhx0fAHebXavYS5rsHLrWKcf4fzhDh6IixJB6mDhT7rEax/9UsoYjzrc1p7VLwbw==} + effect@3.10.3: + resolution: {integrity: sha512-+Z5bUhzTeqYlfoPsfXMZG1pYadqLBKARD3xwMIoEAESsOhKFOrUsHHNCy2ZZW3/6oa4wokgT01k1zavA4BAQ4w==} electron-to-chromium@1.5.28: resolution: {integrity: sha512-VufdJl+rzaKZoYVUijN13QcXVF5dWPZANeFTLNy+OSpHdDL5ynXTF35+60RSBbaQYB1ae723lQXHCrf4pyLsMw==} @@ -17537,18 +17537,18 @@ snapshots: '@discoveryjs/json-ext@0.5.7': {} - '@effect/platform-node-shared@0.19.6(@effect/platform@0.69.6(effect@3.10.2))(effect@3.10.2)': + '@effect/platform-node-shared@0.19.8(@effect/platform@0.69.8(effect@3.10.3))(effect@3.10.3)': dependencies: - '@effect/platform': 0.69.6(effect@3.10.2) + '@effect/platform': 0.69.8(effect@3.10.3) '@parcel/watcher': 2.4.1 - effect: 3.10.2 + effect: 3.10.3 multipasta: 0.2.5 - '@effect/platform-node@0.64.7(@effect/platform@0.69.6(effect@3.10.2))(effect@3.10.2)': + '@effect/platform-node@0.64.9(@effect/platform@0.69.8(effect@3.10.3))(effect@3.10.3)': dependencies: - '@effect/platform': 0.69.6(effect@3.10.2) - '@effect/platform-node-shared': 0.19.6(@effect/platform@0.69.6(effect@3.10.2))(effect@3.10.2) - effect: 3.10.2 + '@effect/platform': 0.69.8(effect@3.10.3) + '@effect/platform-node-shared': 0.19.8(@effect/platform@0.69.8(effect@3.10.3))(effect@3.10.3) + effect: 3.10.3 mime: 3.0.0 undici: 6.19.8 ws: 8.18.0 @@ -17556,15 +17556,15 @@ snapshots: - bufferutil - utf-8-validate - '@effect/platform@0.69.6(effect@3.10.2)': + '@effect/platform@0.69.8(effect@3.10.3)': dependencies: - effect: 3.10.2 + effect: 3.10.3 find-my-way-ts: 0.1.5 multipasta: 0.2.5 - '@effect/vitest@0.13.1(effect@3.10.2)(vitest@2.1.2(@types/node@20.16.11)(@vitest/browser@2.1.2)(happy-dom@13.10.1)(lightningcss@1.24.1)(msw@2.2.13(patch_hash=mpkjv35lscrawpqthnrnago5ai)(typescript@5.6.2))(terser@5.34.1))': + '@effect/vitest@0.13.3(effect@3.10.3)(vitest@2.1.2(@types/node@20.16.11)(@vitest/browser@2.1.2)(happy-dom@13.10.1)(lightningcss@1.24.1)(msw@2.2.13(patch_hash=mpkjv35lscrawpqthnrnago5ai)(typescript@5.6.2))(terser@5.34.1))': dependencies: - effect: 3.10.2 + effect: 3.10.3 vitest: 2.1.2(@types/node@20.16.11)(@vitest/browser@2.1.2(@vitest/spy@2.1.2)(typescript@5.6.2)(vite@5.4.8(@types/node@20.16.11)(lightningcss@1.24.1)(terser@5.34.1))(vitest@2.1.2))(happy-dom@13.10.1)(lightningcss@1.24.1)(msw@2.2.13(patch_hash=mpkjv35lscrawpqthnrnago5ai)(typescript@5.6.2))(terser@5.34.1) '@egjs/agent@2.4.3': {} @@ -24974,7 +24974,7 @@ snapshots: ee-first@1.1.1: {} - effect@3.10.2: + effect@3.10.3: dependencies: fast-check: 3.22.0 From 1170c1463499c4a3cd88fc431baf2b1f518609c5 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Fri, 25 Oct 2024 11:45:52 +0200 Subject: [PATCH 09/15] chore: warn instead of error on version mismatch (#1031) --- packages/uploadthing/src/internal/handler.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/uploadthing/src/internal/handler.ts b/packages/uploadthing/src/internal/handler.ts index c43ea03f97..17ab361591 100644 --- a/packages/uploadthing/src/internal/handler.ts +++ b/packages/uploadthing/src/internal/handler.ts @@ -140,13 +140,10 @@ export const createRequestHandler = ( ); if (clientVersion !== pkgJson.version) { - const msg = `Server version: ${pkgJson.version}, Client version: ${clientVersion}`; - yield* Effect.logError(msg); - return yield* new UploadThingError({ - code: "BAD_REQUEST", - message: "Client version mismatch", - cause: msg, - }); + const serverVersion = pkgJson.version; + yield* Effect.logWarning( + "Client version mismatch. Things may not work as expected, please sync your versions to ensure compatibility.", + ).pipe(Effect.annotateLogs({ clientVersion, serverVersion })); } const { slug, actionType } = yield* HttpRouter.schemaParams( From f7a6b903b6f5089890553a9d02b4ac3586326e26 Mon Sep 17 00:00:00 2001 From: Theo Browne Date: Fri, 25 Oct 2024 02:56:48 -0700 Subject: [PATCH 10/15] =?UTF-8?q?chore(release):=20=F0=9F=93=A6=20=20versi?= =?UTF-8?q?on=20packages=20(#1010)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: juliusmarminge --- .changeset/breezy-windows-admire.md | 10 --- .changeset/chatty-bananas-destroy.md | 5 -- .changeset/flat-seals-change.md | 5 -- .changeset/odd-cheetahs-kneel.md | 5 -- .changeset/orange-roses-sip.md | 6 -- .changeset/sharp-needles-collect.md | 5 -- .changeset/twenty-rings-unite.md | 36 -------- .changeset/two-olives-shop.md | 5 -- .../client-react/package.json | 4 +- .../client-vanilla/package.json | 2 +- .../backend-adapters/client-vue/package.json | 4 +- examples/backend-adapters/package.json | 4 +- examples/backend-adapters/server/package.json | 2 +- examples/minimal-appdir/package.json | 4 +- examples/minimal-astro-react/package.json | 4 +- examples/minimal-expo/package.json | 4 +- examples/minimal-nuxt/package.json | 4 +- examples/minimal-pagedir/package.json | 4 +- examples/minimal-solidstart/package.json | 4 +- examples/minimal-sveltekit/package.json | 4 +- examples/minimal-tanstack-start/package.json | 4 +- examples/with-clerk-appdir/package.json | 4 +- examples/with-clerk-pagesdir/package.json | 4 +- examples/with-clerk-remix/package.json | 4 +- examples/with-drizzle-appdir/package.json | 4 +- examples/with-drizzle-pagesdir/package.json | 4 +- examples/with-novel/package.json | 4 +- examples/with-react-image-crop/package.json | 4 +- examples/with-serveractions/package.json | 2 +- examples/with-tailwindcss/package.json | 4 +- packages/expo/CHANGELOG.md | 36 ++++++++ packages/expo/package.json | 4 +- packages/mime-types/CHANGELOG.md | 6 ++ packages/mime-types/package.json | 2 +- packages/nuxt/CHANGELOG.md | 37 ++++++++ packages/nuxt/package.json | 4 +- packages/react/CHANGELOG.md | 37 ++++++++ packages/react/package.json | 4 +- packages/shared/CHANGELOG.md | 39 +++++++++ packages/shared/package.json | 2 +- packages/solid/CHANGELOG.md | 37 ++++++++ packages/solid/package.json | 4 +- packages/svelte/CHANGELOG.md | 41 +++++++++ packages/svelte/package.json | 4 +- packages/uploadthing/CHANGELOG.md | 42 +++++++++ packages/uploadthing/package.json | 2 +- packages/vue/CHANGELOG.md | 37 ++++++++ packages/vue/package.json | 4 +- pnpm-lock.yaml | 87 ++++++++++--------- 49 files changed, 414 insertions(+), 174 deletions(-) delete mode 100644 .changeset/breezy-windows-admire.md delete mode 100644 .changeset/chatty-bananas-destroy.md delete mode 100644 .changeset/flat-seals-change.md delete mode 100644 .changeset/odd-cheetahs-kneel.md delete mode 100644 .changeset/orange-roses-sip.md delete mode 100644 .changeset/sharp-needles-collect.md delete mode 100644 .changeset/twenty-rings-unite.md delete mode 100644 .changeset/two-olives-shop.md diff --git a/.changeset/breezy-windows-admire.md b/.changeset/breezy-windows-admire.md deleted file mode 100644 index e308c0f64b..0000000000 --- a/.changeset/breezy-windows-admire.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -"@uploadthing/react": patch -"@uploadthing/shared": patch -"@uploadthing/solid": patch -"@uploadthing/svelte": patch -"uploadthing": patch -"@uploadthing/vue": patch ---- - -chore: bump internal effect dependencies (#1005, #1009) diff --git a/.changeset/chatty-bananas-destroy.md b/.changeset/chatty-bananas-destroy.md deleted file mode 100644 index 4149ed9f79..0000000000 --- a/.changeset/chatty-bananas-destroy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"uploadthing": patch ---- - -fix: server handler not receiving the right middleware args when passed `{ request: Request }` instead of just Request (#1017) diff --git a/.changeset/flat-seals-change.md b/.changeset/flat-seals-change.md deleted file mode 100644 index 90a853522b..0000000000 --- a/.changeset/flat-seals-change.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@uploadthing/svelte": patch ---- - -chore: update svelte peer dep range diff --git a/.changeset/odd-cheetahs-kneel.md b/.changeset/odd-cheetahs-kneel.md deleted file mode 100644 index 5420c8e725..0000000000 --- a/.changeset/odd-cheetahs-kneel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@uploadthing/svelte": patch ---- - -chore: allow svelte v5 peer dep (#1006) diff --git a/.changeset/orange-roses-sip.md b/.changeset/orange-roses-sip.md deleted file mode 100644 index 47bd9655c4..0000000000 --- a/.changeset/orange-roses-sip.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@uploadthing/shared": patch -"uploadthing": patch ---- - -chore: redact sensitive fields from logs using `effect/Redacted` diff --git a/.changeset/sharp-needles-collect.md b/.changeset/sharp-needles-collect.md deleted file mode 100644 index f483894d8b..0000000000 --- a/.changeset/sharp-needles-collect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@uploadthing/nuxt": patch ---- - -fix: options was not forwarded to uploadthing handler correctly diff --git a/.changeset/twenty-rings-unite.md b/.changeset/twenty-rings-unite.md deleted file mode 100644 index c84e04ecb3..0000000000 --- a/.changeset/twenty-rings-unite.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -"uploadthing": minor -"@uploadthing/shared": minor -"@uploadthing/svelte": minor -"@uploadthing/react": minor -"@uploadthing/solid": minor -"@uploadthing/vue": minor -"@uploadthing/nuxt": minor -"@uploadthing/expo": minor ---- - -feat: add support to specify route endpoint that supports "Go to Definition" - -All places that accept the `endpoint` argument now additionally accept a function that gets a route registry as input and returns the endpoint to use. This allows for "Go to Definition" to go to the backend route definition directly from the component. - -### Examples - -```ts -// uploadthing/client#uploadFiles -uploadFiles( - (routeRegistry) => routeRegistry.videoAndImage, - { ... } -) - -// uploadthing/react#useUploadThing -useUploadThing( - (routeRegistry) => routeRegistry.videoAndImage, - { ... } -) - -// uploadthing/react#UploadButton - routeRegistry.videoAndImage} - { ... } -/> -``` diff --git a/.changeset/two-olives-shop.md b/.changeset/two-olives-shop.md deleted file mode 100644 index e869a56a8f..0000000000 --- a/.changeset/two-olives-shop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@uploadthing/mime-types": patch ---- - -feat(@uploadthing/mime-types) add application/yaml as mime type diff --git a/examples/backend-adapters/client-react/package.json b/examples/backend-adapters/client-react/package.json index 1b9f0bdaf8..06ee87ccf6 100644 --- a/examples/backend-adapters/client-react/package.json +++ b/examples/backend-adapters/client-react/package.json @@ -8,10 +8,10 @@ "start": "vite preview" }, "dependencies": { - "@uploadthing/react": "7.0.3", + "@uploadthing/react": "7.1.0", "react": "18.3.1", "react-dom": "18.3.1", - "uploadthing": "7.1.0" + "uploadthing": "7.2.0" }, "devDependencies": { "@types/react": "18.3.3", diff --git a/examples/backend-adapters/client-vanilla/package.json b/examples/backend-adapters/client-vanilla/package.json index 09b5faf601..a5cb61cf4a 100644 --- a/examples/backend-adapters/client-vanilla/package.json +++ b/examples/backend-adapters/client-vanilla/package.json @@ -9,7 +9,7 @@ "preview": "vite preview" }, "dependencies": { - "uploadthing": "7.1.0" + "uploadthing": "7.2.0" }, "devDependencies": { "typescript": "^5.5.2", diff --git a/examples/backend-adapters/client-vue/package.json b/examples/backend-adapters/client-vue/package.json index bd5b7f9216..c2afebf0be 100644 --- a/examples/backend-adapters/client-vue/package.json +++ b/examples/backend-adapters/client-vue/package.json @@ -8,8 +8,8 @@ "preview": "vite preview" }, "dependencies": { - "@uploadthing/vue": "7.0.3", - "uploadthing": "7.1.0", + "@uploadthing/vue": "7.1.0", + "uploadthing": "7.2.0", "vue": "^3.4.21" }, "devDependencies": { diff --git a/examples/backend-adapters/package.json b/examples/backend-adapters/package.json index 05c254bae0..957f7a23db 100644 --- a/examples/backend-adapters/package.json +++ b/examples/backend-adapters/package.json @@ -24,9 +24,9 @@ }, "dependencies": { "@playwright/test": "1.45.0", - "@uploadthing/react": "7.0.3", + "@uploadthing/react": "7.1.0", "concurrently": "^8.2.2", "typescript": "^5.5.2", - "uploadthing": "7.1.0" + "uploadthing": "7.2.0" } } diff --git a/examples/backend-adapters/server/package.json b/examples/backend-adapters/server/package.json index 63a46fbb01..9a55e56113 100644 --- a/examples/backend-adapters/server/package.json +++ b/examples/backend-adapters/server/package.json @@ -26,7 +26,7 @@ "h3": "^1.11.1", "hono": "^4.0.8", "listhen": "^1.7.2", - "uploadthing": "7.1.0" + "uploadthing": "7.2.0" }, "devDependencies": { "@cloudflare/workers-types": "^4.20240620.0", diff --git a/examples/minimal-appdir/package.json b/examples/minimal-appdir/package.json index 27a092e333..f4b3ac9cef 100644 --- a/examples/minimal-appdir/package.json +++ b/examples/minimal-appdir/package.json @@ -9,11 +9,11 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@uploadthing/react": "7.0.3", + "@uploadthing/react": "7.1.0", "next": "14.2.11", "react": "18.3.1", "react-dom": "18.3.1", - "uploadthing": "7.1.0" + "uploadthing": "7.2.0" }, "devDependencies": { "@next/bundle-analyzer": "14.2.3", diff --git a/examples/minimal-astro-react/package.json b/examples/minimal-astro-react/package.json index f723d7ff31..6a49220454 100644 --- a/examples/minimal-astro-react/package.json +++ b/examples/minimal-astro-react/package.json @@ -12,11 +12,11 @@ "dependencies": { "@astrojs/node": "^8.2.1", "@astrojs/react": "^3.0.10", - "@uploadthing/react": "7.0.3", + "@uploadthing/react": "7.1.0", "astro": "^4.4.5", "react": "18.3.1", "react-dom": "18.3.1", - "uploadthing": "7.1.0" + "uploadthing": "7.2.0" }, "devDependencies": { "@types/react": "18.3.3", diff --git a/examples/minimal-expo/package.json b/examples/minimal-expo/package.json index a4100431a8..9e09857abe 100644 --- a/examples/minimal-expo/package.json +++ b/examples/minimal-expo/package.json @@ -18,7 +18,7 @@ "@trpc/client": "11.0.0-rc.452", "@trpc/react-query": "11.0.0-rc.452", "@trpc/server": "11.0.0-rc.452", - "@uploadthing/expo": "7.0.3", + "@uploadthing/expo": "7.1.0", "expo": "~51.0.8", "expo-dev-client": "~4.0.10", "expo-document-picker": "^12.0.1", @@ -39,7 +39,7 @@ "react-native-safe-area-context": "4.10.1", "react-native-screens": "~3.31.1", "react-native-web": "~0.19.12", - "uploadthing": "7.1.0", + "uploadthing": "7.2.0", "zod": "^3.23.8" }, "devDependencies": { diff --git a/examples/minimal-nuxt/package.json b/examples/minimal-nuxt/package.json index 7d359fcc4d..8736519b43 100644 --- a/examples/minimal-nuxt/package.json +++ b/examples/minimal-nuxt/package.json @@ -9,9 +9,9 @@ "preview": "nuxt preview" }, "dependencies": { - "@uploadthing/nuxt": "7.0.3", + "@uploadthing/nuxt": "7.1.0", "nuxt": "^3.11.2", - "uploadthing": "7.1.0", + "uploadthing": "7.2.0", "vue": "^3.4.21", "vue-router": "^4.3.0" } diff --git a/examples/minimal-pagedir/package.json b/examples/minimal-pagedir/package.json index b84a2ad722..75ab7b667d 100644 --- a/examples/minimal-pagedir/package.json +++ b/examples/minimal-pagedir/package.json @@ -9,11 +9,11 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@uploadthing/react": "7.0.3", + "@uploadthing/react": "7.1.0", "next": "14.2.11", "react": "18.3.1", "react-dom": "18.3.1", - "uploadthing": "7.1.0" + "uploadthing": "7.2.0" }, "devDependencies": { "@types/node": "^20.14.0", diff --git a/examples/minimal-solidstart/package.json b/examples/minimal-solidstart/package.json index 104c7a6106..6658e7b1a6 100644 --- a/examples/minimal-solidstart/package.json +++ b/examples/minimal-solidstart/package.json @@ -13,9 +13,9 @@ "@solidjs/meta": "^0.29.4", "@solidjs/router": "^0.14.5", "@solidjs/start": "^1.0.6", - "@uploadthing/solid": "7.0.3", + "@uploadthing/solid": "7.1.0", "solid-js": "^1.8.23", - "uploadthing": "7.1.0", + "uploadthing": "7.2.0", "vinxi": "^0.4.3" }, "engines": { diff --git a/examples/minimal-sveltekit/package.json b/examples/minimal-sveltekit/package.json index 55ceecdfce..0d1bdb5e01 100644 --- a/examples/minimal-sveltekit/package.json +++ b/examples/minimal-sveltekit/package.json @@ -13,8 +13,8 @@ }, "dependencies": { "@fontsource-variable/inter": "^5.0.17", - "@uploadthing/svelte": "7.0.3", - "uploadthing": "7.1.0" + "@uploadthing/svelte": "7.1.0", + "uploadthing": "7.2.0" }, "devDependencies": { "@sveltejs/adapter-auto": "^3.1.1", diff --git a/examples/minimal-tanstack-start/package.json b/examples/minimal-tanstack-start/package.json index a73de3f4d3..b040ee1f80 100644 --- a/examples/minimal-tanstack-start/package.json +++ b/examples/minimal-tanstack-start/package.json @@ -10,10 +10,10 @@ "dependencies": { "@tanstack/react-router": "^1.69.1", "@tanstack/start": "^1.69.3", - "@uploadthing/react": "^7.0.3", + "@uploadthing/react": "^7.1.0", "react": "18.3.1", "react-dom": "18.3.1", - "uploadthing": "7.1.0", + "uploadthing": "7.2.0", "vinxi": "^0.4.3" }, "devDependencies": { diff --git a/examples/with-clerk-appdir/package.json b/examples/with-clerk-appdir/package.json index c875796799..52a1f5003c 100644 --- a/examples/with-clerk-appdir/package.json +++ b/examples/with-clerk-appdir/package.json @@ -12,11 +12,11 @@ "dependencies": { "@clerk/nextjs": "^4.29.8", "@t3-oss/env-nextjs": "^0.10.1", - "@uploadthing/react": "7.0.3", + "@uploadthing/react": "7.1.0", "next": "14.2.11", "react": "18.3.1", "react-dom": "18.3.1", - "uploadthing": "7.1.0", + "uploadthing": "7.2.0", "zod": "^3.23.8" }, "devDependencies": { diff --git a/examples/with-clerk-pagesdir/package.json b/examples/with-clerk-pagesdir/package.json index 436dffe107..b60c627f14 100644 --- a/examples/with-clerk-pagesdir/package.json +++ b/examples/with-clerk-pagesdir/package.json @@ -12,11 +12,11 @@ "dependencies": { "@clerk/nextjs": "^4.29.8", "@t3-oss/env-nextjs": "^0.10.1", - "@uploadthing/react": "7.0.3", + "@uploadthing/react": "7.1.0", "next": "14.2.11", "react": "18.3.1", "react-dom": "18.3.1", - "uploadthing": "7.1.0", + "uploadthing": "7.2.0", "zod": "^3.23.8" }, "devDependencies": { diff --git a/examples/with-clerk-remix/package.json b/examples/with-clerk-remix/package.json index 0957a03f2e..ed110886fa 100644 --- a/examples/with-clerk-remix/package.json +++ b/examples/with-clerk-remix/package.json @@ -14,11 +14,11 @@ "@remix-run/node": "^2.12.0", "@remix-run/react": "^2.12.0", "@remix-run/serve": "^2.12.0", - "@uploadthing/react": "7.0.3", + "@uploadthing/react": "7.1.0", "isbot": "^4.1.0", "react": "18.3.1", "react-dom": "18.3.1", - "uploadthing": "7.1.0" + "uploadthing": "7.2.0" }, "devDependencies": { "@remix-run/dev": "^2.12.0", diff --git a/examples/with-drizzle-appdir/package.json b/examples/with-drizzle-appdir/package.json index d89b905cff..c81cc84699 100644 --- a/examples/with-drizzle-appdir/package.json +++ b/examples/with-drizzle-appdir/package.json @@ -12,12 +12,12 @@ "dependencies": { "@libsql/client": "^0.6.0", "@t3-oss/env-nextjs": "^0.10.1", - "@uploadthing/react": "7.0.3", + "@uploadthing/react": "7.1.0", "drizzle-orm": "^0.30.10", "next": "14.2.11", "react": "18.3.1", "react-dom": "18.3.1", - "uploadthing": "7.1.0", + "uploadthing": "7.2.0", "zod": "^3.23.8" }, "devDependencies": { diff --git a/examples/with-drizzle-pagesdir/package.json b/examples/with-drizzle-pagesdir/package.json index 7df249c8e9..66d03e2edf 100644 --- a/examples/with-drizzle-pagesdir/package.json +++ b/examples/with-drizzle-pagesdir/package.json @@ -12,13 +12,13 @@ "dependencies": { "@libsql/client": "^0.6.0", "@t3-oss/env-nextjs": "^0.10.1", - "@uploadthing/react": "7.0.3", + "@uploadthing/react": "7.1.0", "drizzle-orm": "^0.30.10", "next": "14.2.11", "react": "18.3.1", "react-dom": "18.3.1", "swr": "^2.2.5", - "uploadthing": "7.1.0", + "uploadthing": "7.2.0", "zod": "^3.23.8" }, "devDependencies": { diff --git a/examples/with-novel/package.json b/examples/with-novel/package.json index c70991869a..664c7eaf5e 100644 --- a/examples/with-novel/package.json +++ b/examples/with-novel/package.json @@ -13,7 +13,7 @@ "@radix-ui/react-popover": "^1.0.6", "@radix-ui/react-slot": "^1.0.2", "@tailwindcss/typography": "^0.5.10", - "@uploadthing/react": "^7.0.3", + "@uploadthing/react": "^7.1.0", "class-variance-authority": "^0.7.0", "cmdk": "^0.2.1", "lucide-react": "^0.368.0", @@ -24,7 +24,7 @@ "react-dom": "18.3.1", "sonner": "^1.4.41", "tailwind-merge": "^2.2.1", - "uploadthing": "7.1.0", + "uploadthing": "7.2.0", "use-debounce": "^9.0.3" }, "devDependencies": { diff --git a/examples/with-react-image-crop/package.json b/examples/with-react-image-crop/package.json index 44178a8199..53d856fea1 100644 --- a/examples/with-react-image-crop/package.json +++ b/examples/with-react-image-crop/package.json @@ -9,12 +9,12 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@uploadthing/react": "7.0.3", + "@uploadthing/react": "7.1.0", "next": "14.2.11", "react": "18.3.1", "react-dom": "18.3.1", "react-image-crop": "^11.0.5", - "uploadthing": "7.1.0" + "uploadthing": "7.2.0" }, "devDependencies": { "@types/node": "^20.14.0", diff --git a/examples/with-serveractions/package.json b/examples/with-serveractions/package.json index 773a993ee6..d73288ea3e 100644 --- a/examples/with-serveractions/package.json +++ b/examples/with-serveractions/package.json @@ -12,7 +12,7 @@ "next": "14.2.11", "react": "18.3.1", "react-dom": "18.3.1", - "uploadthing": "7.1.0" + "uploadthing": "7.2.0" }, "devDependencies": { "@types/node": "^20.14.0", diff --git a/examples/with-tailwindcss/package.json b/examples/with-tailwindcss/package.json index 4615f03a1c..df4d71dc97 100644 --- a/examples/with-tailwindcss/package.json +++ b/examples/with-tailwindcss/package.json @@ -9,11 +9,11 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@uploadthing/react": "7.0.3", + "@uploadthing/react": "7.1.0", "next": "14.2.11", "react": "18.3.1", "react-dom": "18.3.1", - "uploadthing": "7.1.0" + "uploadthing": "7.2.0" }, "devDependencies": { "@types/node": "^20.14.0", diff --git a/packages/expo/CHANGELOG.md b/packages/expo/CHANGELOG.md index f6a759f1d2..8a9ff2fa8d 100644 --- a/packages/expo/CHANGELOG.md +++ b/packages/expo/CHANGELOG.md @@ -1,5 +1,41 @@ # @uploadthing/expo +## 7.1.0 + +### Minor Changes + +- [#1008](https://github.com/pingdotgg/uploadthing/pull/1008) [`3acc199`](https://github.com/pingdotgg/uploadthing/commit/3acc199821637bda1605cd7130325e8783710908) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: add support to specify route endpoint that supports "Go to Definition" + + All places that accept the `endpoint` argument now additionally accept a function that gets a route registry as input and returns the endpoint to use. This allows for "Go to Definition" to go to the backend route definition directly from the component. + + ### Examples + + ```ts + // uploadthing/client#uploadFiles + uploadFiles( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#useUploadThing + useUploadThing( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#UploadButton + routeRegistry.videoAndImage} + { ... } + /> + ``` + +### Patch Changes + +- Updated dependencies [[`01b1363`](https://github.com/pingdotgg/uploadthing/commit/01b136310de7d620c3298d16f6cbd255e168c7e5), [`72ac250`](https://github.com/pingdotgg/uploadthing/commit/72ac25044f14d2c0b5c5b870b9bb4218c766abf2), [`3acc199`](https://github.com/pingdotgg/uploadthing/commit/3acc199821637bda1605cd7130325e8783710908)]: + - @uploadthing/react@7.1.0 + - @uploadthing/shared@7.1.0 + ## 7.0.3 ### Patch Changes diff --git a/packages/expo/package.json b/packages/expo/package.json index 68175c8f93..4afce2a07e 100644 --- a/packages/expo/package.json +++ b/packages/expo/package.json @@ -1,6 +1,6 @@ { "name": "@uploadthing/expo", - "version": "7.0.3", + "version": "7.1.0", "type": "module", "license": "MIT", "main": "dist/index.cjs", @@ -57,7 +57,7 @@ "expo-image-picker": "^14.0.0 || ^15.0.0", "react": "^17.0.2 || ^18.0.0", "react-native": "*", - "uploadthing": "^7.0.0" + "uploadthing": "^7.2.0" }, "peerDependenciesMeta": { "@uploadthing/mime-types": { diff --git a/packages/mime-types/CHANGELOG.md b/packages/mime-types/CHANGELOG.md index b45e2bab11..f68a47c294 100644 --- a/packages/mime-types/CHANGELOG.md +++ b/packages/mime-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @uploadthing/mime-types +## 0.3.1 + +### Patch Changes + +- [#1022](https://github.com/pingdotgg/uploadthing/pull/1022) [`e2df2a2`](https://github.com/pingdotgg/uploadthing/commit/e2df2a29a9674ebf62091ebfd87706e084e5046b) Thanks [@christian-bromann](https://github.com/christian-bromann)! - feat(@uploadthing/mime-types) add application/yaml as mime type + ## 0.3.0 ### Minor Changes diff --git a/packages/mime-types/package.json b/packages/mime-types/package.json index 4bb3290705..5c418a70d1 100644 --- a/packages/mime-types/package.json +++ b/packages/mime-types/package.json @@ -1,6 +1,6 @@ { "name": "@uploadthing/mime-types", - "version": "0.3.0", + "version": "0.3.1", "type": "module", "sideEffects": false, "license": "MIT", diff --git a/packages/nuxt/CHANGELOG.md b/packages/nuxt/CHANGELOG.md index 56f3436d79..8dc7994f74 100644 --- a/packages/nuxt/CHANGELOG.md +++ b/packages/nuxt/CHANGELOG.md @@ -1,5 +1,42 @@ # @uploadthing/nuxt +## 7.1.0 + +### Minor Changes + +- [#1008](https://github.com/pingdotgg/uploadthing/pull/1008) [`3acc199`](https://github.com/pingdotgg/uploadthing/commit/3acc199821637bda1605cd7130325e8783710908) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: add support to specify route endpoint that supports "Go to Definition" + + All places that accept the `endpoint` argument now additionally accept a function that gets a route registry as input and returns the endpoint to use. This allows for "Go to Definition" to go to the backend route definition directly from the component. + + ### Examples + + ```ts + // uploadthing/client#uploadFiles + uploadFiles( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#useUploadThing + useUploadThing( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#UploadButton + routeRegistry.videoAndImage} + { ... } + /> + ``` + +### Patch Changes + +- [#1018](https://github.com/pingdotgg/uploadthing/pull/1018) [`06c6787`](https://github.com/pingdotgg/uploadthing/commit/06c6787aacb7bf52919c1c767bef8b315010725c) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - fix: options was not forwarded to uploadthing handler correctly + +- Updated dependencies [[`01b1363`](https://github.com/pingdotgg/uploadthing/commit/01b136310de7d620c3298d16f6cbd255e168c7e5), [`3acc199`](https://github.com/pingdotgg/uploadthing/commit/3acc199821637bda1605cd7130325e8783710908)]: + - @uploadthing/vue@7.1.0 + ## 7.0.3 ### Patch Changes diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index 38f5719e61..06c774ef08 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -1,6 +1,6 @@ { "name": "@uploadthing/nuxt", - "version": "7.0.3", + "version": "7.1.0", "type": "module", "license": "MIT", "exports": { @@ -43,7 +43,7 @@ "uploadthing": "workspace:*" }, "peerDependencies": { - "uploadthing": "^7.0.0" + "uploadthing": "^7.2.0" }, "eslintConfig": { "root": true, diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index cae869207d..91d6a237b2 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,42 @@ # @uploadthing/react +## 7.1.0 + +### Minor Changes + +- [#1008](https://github.com/pingdotgg/uploadthing/pull/1008) [`3acc199`](https://github.com/pingdotgg/uploadthing/commit/3acc199821637bda1605cd7130325e8783710908) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: add support to specify route endpoint that supports "Go to Definition" + + All places that accept the `endpoint` argument now additionally accept a function that gets a route registry as input and returns the endpoint to use. This allows for "Go to Definition" to go to the backend route definition directly from the component. + + ### Examples + + ```ts + // uploadthing/client#uploadFiles + uploadFiles( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#useUploadThing + useUploadThing( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#UploadButton + routeRegistry.videoAndImage} + { ... } + /> + ``` + +### Patch Changes + +- [`01b1363`](https://github.com/pingdotgg/uploadthing/commit/01b136310de7d620c3298d16f6cbd255e168c7e5) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: bump internal effect dependencies (#1005, #1009) + +- Updated dependencies [[`01b1363`](https://github.com/pingdotgg/uploadthing/commit/01b136310de7d620c3298d16f6cbd255e168c7e5), [`72ac250`](https://github.com/pingdotgg/uploadthing/commit/72ac25044f14d2c0b5c5b870b9bb4218c766abf2), [`3acc199`](https://github.com/pingdotgg/uploadthing/commit/3acc199821637bda1605cd7130325e8783710908)]: + - @uploadthing/shared@7.1.0 + ## 7.0.3 ### Patch Changes diff --git a/packages/react/package.json b/packages/react/package.json index 1fc08ac556..4e0241f830 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@uploadthing/react", - "version": "7.0.3", + "version": "7.1.0", "type": "module", "sideEffects": false, "license": "MIT", @@ -68,7 +68,7 @@ "peerDependencies": { "next": "*", "react": "^17.0.2 || ^18.0.0", - "uploadthing": "^7.0.0" + "uploadthing": "^7.2.0" }, "peerDependenciesMeta": { "next": { diff --git a/packages/shared/CHANGELOG.md b/packages/shared/CHANGELOG.md index 3ec0d0339d..c7f86214b8 100644 --- a/packages/shared/CHANGELOG.md +++ b/packages/shared/CHANGELOG.md @@ -1,5 +1,44 @@ # @uploadthing/shared +## 7.1.0 + +### Minor Changes + +- [#1008](https://github.com/pingdotgg/uploadthing/pull/1008) [`3acc199`](https://github.com/pingdotgg/uploadthing/commit/3acc199821637bda1605cd7130325e8783710908) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: add support to specify route endpoint that supports "Go to Definition" + + All places that accept the `endpoint` argument now additionally accept a function that gets a route registry as input and returns the endpoint to use. This allows for "Go to Definition" to go to the backend route definition directly from the component. + + ### Examples + + ```ts + // uploadthing/client#uploadFiles + uploadFiles( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#useUploadThing + useUploadThing( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#UploadButton + routeRegistry.videoAndImage} + { ... } + /> + ``` + +### Patch Changes + +- [`01b1363`](https://github.com/pingdotgg/uploadthing/commit/01b136310de7d620c3298d16f6cbd255e168c7e5) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: bump internal effect dependencies (#1005, #1009) + +- [#993](https://github.com/pingdotgg/uploadthing/pull/993) [`72ac250`](https://github.com/pingdotgg/uploadthing/commit/72ac25044f14d2c0b5c5b870b9bb4218c766abf2) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: redact sensitive fields from logs using `effect/Redacted` + +- Updated dependencies [[`e2df2a2`](https://github.com/pingdotgg/uploadthing/commit/e2df2a29a9674ebf62091ebfd87706e084e5046b)]: + - @uploadthing/mime-types@0.3.1 + ## 7.0.3 ### Patch Changes diff --git a/packages/shared/package.json b/packages/shared/package.json index db50972bfa..7b354db4bc 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@uploadthing/shared", - "version": "7.0.3", + "version": "7.1.0", "type": "module", "sideEffects": false, "license": "MIT", diff --git a/packages/solid/CHANGELOG.md b/packages/solid/CHANGELOG.md index 06d0d409d7..300a54ed6e 100644 --- a/packages/solid/CHANGELOG.md +++ b/packages/solid/CHANGELOG.md @@ -1,5 +1,42 @@ # @uploadthing/solid +## 7.1.0 + +### Minor Changes + +- [#1008](https://github.com/pingdotgg/uploadthing/pull/1008) [`3acc199`](https://github.com/pingdotgg/uploadthing/commit/3acc199821637bda1605cd7130325e8783710908) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: add support to specify route endpoint that supports "Go to Definition" + + All places that accept the `endpoint` argument now additionally accept a function that gets a route registry as input and returns the endpoint to use. This allows for "Go to Definition" to go to the backend route definition directly from the component. + + ### Examples + + ```ts + // uploadthing/client#uploadFiles + uploadFiles( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#useUploadThing + useUploadThing( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#UploadButton + routeRegistry.videoAndImage} + { ... } + /> + ``` + +### Patch Changes + +- [`01b1363`](https://github.com/pingdotgg/uploadthing/commit/01b136310de7d620c3298d16f6cbd255e168c7e5) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: bump internal effect dependencies (#1005, #1009) + +- Updated dependencies [[`01b1363`](https://github.com/pingdotgg/uploadthing/commit/01b136310de7d620c3298d16f6cbd255e168c7e5), [`72ac250`](https://github.com/pingdotgg/uploadthing/commit/72ac25044f14d2c0b5c5b870b9bb4218c766abf2), [`3acc199`](https://github.com/pingdotgg/uploadthing/commit/3acc199821637bda1605cd7130325e8783710908)]: + - @uploadthing/shared@7.1.0 + ## 7.0.3 ### Patch Changes diff --git a/packages/solid/package.json b/packages/solid/package.json index 9f08911659..e8ddd3925d 100644 --- a/packages/solid/package.json +++ b/packages/solid/package.json @@ -3,7 +3,7 @@ "type": "module", "author": "OrJDev", "license": "MIT", - "version": "7.0.3", + "version": "7.1.0", "main": "./dist/server.cjs", "module": "./dist/server.js", "types": "./dist/index.d.ts", @@ -125,7 +125,7 @@ }, "peerDependencies": { "solid-js": "^1.5.3", - "uploadthing": "^7.0.0" + "uploadthing": "^7.2.0" }, "keywords": [ "SolidJS", diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 5e76dbc08f..2921e410f0 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,46 @@ # @uploadthing/svelte +## 7.1.0 + +### Minor Changes + +- [#1008](https://github.com/pingdotgg/uploadthing/pull/1008) [`3acc199`](https://github.com/pingdotgg/uploadthing/commit/3acc199821637bda1605cd7130325e8783710908) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: add support to specify route endpoint that supports "Go to Definition" + + All places that accept the `endpoint` argument now additionally accept a function that gets a route registry as input and returns the endpoint to use. This allows for "Go to Definition" to go to the backend route definition directly from the component. + + ### Examples + + ```ts + // uploadthing/client#uploadFiles + uploadFiles( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#useUploadThing + useUploadThing( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#UploadButton + routeRegistry.videoAndImage} + { ... } + /> + ``` + +### Patch Changes + +- [`01b1363`](https://github.com/pingdotgg/uploadthing/commit/01b136310de7d620c3298d16f6cbd255e168c7e5) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: bump internal effect dependencies (#1005, #1009) + +- [#1029](https://github.com/pingdotgg/uploadthing/pull/1029) [`176b2e9`](https://github.com/pingdotgg/uploadthing/commit/176b2e9ed98a3e802182d95e34adbfcfe667d120) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: update svelte peer dep range + +- [`f73f393`](https://github.com/pingdotgg/uploadthing/commit/f73f39320f7c914a37df50c2bab4de2aacea3089) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: allow svelte v5 peer dep (#1006) + +- Updated dependencies [[`01b1363`](https://github.com/pingdotgg/uploadthing/commit/01b136310de7d620c3298d16f6cbd255e168c7e5), [`72ac250`](https://github.com/pingdotgg/uploadthing/commit/72ac25044f14d2c0b5c5b870b9bb4218c766abf2), [`3acc199`](https://github.com/pingdotgg/uploadthing/commit/3acc199821637bda1605cd7130325e8783710908)]: + - @uploadthing/shared@7.1.0 + ## 7.0.3 ### Patch Changes diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 4ff2114ae9..432e808cc8 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -1,6 +1,6 @@ { "name": "@uploadthing/svelte", - "version": "7.0.3", + "version": "7.1.0", "license": "MIT", "scripts": { "dev": "vite dev", @@ -30,7 +30,7 @@ ], "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0", - "uploadthing": "^7.0.0" + "uploadthing": "^7.2.0" }, "dependencies": { "@uploadthing/shared": "workspace:*", diff --git a/packages/uploadthing/CHANGELOG.md b/packages/uploadthing/CHANGELOG.md index e178d7b976..8a9b540008 100644 --- a/packages/uploadthing/CHANGELOG.md +++ b/packages/uploadthing/CHANGELOG.md @@ -1,5 +1,47 @@ # uploadthing +## 7.2.0 + +### Minor Changes + +- [#1008](https://github.com/pingdotgg/uploadthing/pull/1008) [`3acc199`](https://github.com/pingdotgg/uploadthing/commit/3acc199821637bda1605cd7130325e8783710908) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: add support to specify route endpoint that supports "Go to Definition" + + All places that accept the `endpoint` argument now additionally accept a function that gets a route registry as input and returns the endpoint to use. This allows for "Go to Definition" to go to the backend route definition directly from the component. + + ### Examples + + ```ts + // uploadthing/client#uploadFiles + uploadFiles( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#useUploadThing + useUploadThing( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#UploadButton + routeRegistry.videoAndImage} + { ... } + /> + ``` + +### Patch Changes + +- [`01b1363`](https://github.com/pingdotgg/uploadthing/commit/01b136310de7d620c3298d16f6cbd255e168c7e5) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: bump internal effect dependencies (#1005, #1009) + +- [`426b461`](https://github.com/pingdotgg/uploadthing/commit/426b4611ef6613df4a1fefcbe5d0512acced6966) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - fix: server handler not receiving the right middleware args when passed `{ request: Request }` instead of just Request (#1017) + +- [#993](https://github.com/pingdotgg/uploadthing/pull/993) [`72ac250`](https://github.com/pingdotgg/uploadthing/commit/72ac25044f14d2c0b5c5b870b9bb4218c766abf2) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: redact sensitive fields from logs using `effect/Redacted` + +- Updated dependencies [[`01b1363`](https://github.com/pingdotgg/uploadthing/commit/01b136310de7d620c3298d16f6cbd255e168c7e5), [`72ac250`](https://github.com/pingdotgg/uploadthing/commit/72ac25044f14d2c0b5c5b870b9bb4218c766abf2), [`3acc199`](https://github.com/pingdotgg/uploadthing/commit/3acc199821637bda1605cd7130325e8783710908), [`e2df2a2`](https://github.com/pingdotgg/uploadthing/commit/e2df2a29a9674ebf62091ebfd87706e084e5046b)]: + - @uploadthing/shared@7.1.0 + - @uploadthing/mime-types@0.3.1 + ## 7.1.0 ### Minor Changes diff --git a/packages/uploadthing/package.json b/packages/uploadthing/package.json index 50675002b6..418fcd3e79 100644 --- a/packages/uploadthing/package.json +++ b/packages/uploadthing/package.json @@ -1,6 +1,6 @@ { "name": "uploadthing", - "version": "7.1.0", + "version": "7.2.0", "type": "module", "sideEffects": false, "engines": { diff --git a/packages/vue/CHANGELOG.md b/packages/vue/CHANGELOG.md index ffe93f7dc7..15645b9832 100644 --- a/packages/vue/CHANGELOG.md +++ b/packages/vue/CHANGELOG.md @@ -1,5 +1,42 @@ # @uploadthing/vue +## 7.1.0 + +### Minor Changes + +- [#1008](https://github.com/pingdotgg/uploadthing/pull/1008) [`3acc199`](https://github.com/pingdotgg/uploadthing/commit/3acc199821637bda1605cd7130325e8783710908) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: add support to specify route endpoint that supports "Go to Definition" + + All places that accept the `endpoint` argument now additionally accept a function that gets a route registry as input and returns the endpoint to use. This allows for "Go to Definition" to go to the backend route definition directly from the component. + + ### Examples + + ```ts + // uploadthing/client#uploadFiles + uploadFiles( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#useUploadThing + useUploadThing( + (routeRegistry) => routeRegistry.videoAndImage, + { ... } + ) + + // uploadthing/react#UploadButton + routeRegistry.videoAndImage} + { ... } + /> + ``` + +### Patch Changes + +- [`01b1363`](https://github.com/pingdotgg/uploadthing/commit/01b136310de7d620c3298d16f6cbd255e168c7e5) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: bump internal effect dependencies (#1005, #1009) + +- Updated dependencies [[`01b1363`](https://github.com/pingdotgg/uploadthing/commit/01b136310de7d620c3298d16f6cbd255e168c7e5), [`72ac250`](https://github.com/pingdotgg/uploadthing/commit/72ac25044f14d2c0b5c5b870b9bb4218c766abf2), [`3acc199`](https://github.com/pingdotgg/uploadthing/commit/3acc199821637bda1605cd7130325e8783710908)]: + - @uploadthing/shared@7.1.0 + ## 7.0.3 ### Patch Changes diff --git a/packages/vue/package.json b/packages/vue/package.json index daa0be5bf7..2dec28ff97 100644 --- a/packages/vue/package.json +++ b/packages/vue/package.json @@ -1,6 +1,6 @@ { "name": "@uploadthing/vue", - "version": "7.0.3", + "version": "7.1.0", "type": "module", "sideEffects": false, "license": "MIT", @@ -56,7 +56,7 @@ "wait-on": "^7.2.0" }, "peerDependencies": { - "uploadthing": "^7.0.0", + "uploadthing": "^7.2.0", "vue": "^3.4.0" }, "eslintConfig": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9724ae1d6c..6556e01a87 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -261,7 +261,7 @@ importers: specifier: 1.45.0 version: 1.45.0 '@uploadthing/react': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../packages/react concurrently: specifier: ^8.2.2 @@ -270,13 +270,13 @@ importers: specifier: ^5.5.2 version: 5.6.2 uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing examples/backend-adapters/client-react: dependencies: '@uploadthing/react': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../../packages/react react: specifier: 18.3.1 @@ -285,7 +285,7 @@ importers: specifier: 18.3.1 version: 18.3.1(react@18.3.1) uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../../packages/uploadthing devDependencies: '@types/react': @@ -307,7 +307,7 @@ importers: examples/backend-adapters/client-vanilla: dependencies: uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../../packages/uploadthing devDependencies: typescript: @@ -320,10 +320,10 @@ importers: examples/backend-adapters/client-vue: dependencies: '@uploadthing/vue': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../../packages/vue uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../../packages/uploadthing vue: specifier: ^3.4.21 @@ -387,7 +387,7 @@ importers: specifier: ^1.7.2 version: 1.7.2 uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../../packages/uploadthing devDependencies: '@cloudflare/workers-types': @@ -412,7 +412,7 @@ importers: examples/minimal-appdir: dependencies: '@uploadthing/react': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../packages/react next: specifier: 14.2.11 @@ -424,7 +424,7 @@ importers: specifier: 18.3.1 version: 18.3.1(react@18.3.1) uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing devDependencies: '@next/bundle-analyzer': @@ -452,7 +452,7 @@ importers: specifier: ^3.0.10 version: 3.3.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(vite@5.4.8(@types/node@22.7.5)(lightningcss@1.24.1)(terser@5.34.1)) '@uploadthing/react': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../packages/react astro: specifier: ^4.4.5 @@ -464,7 +464,7 @@ importers: specifier: 18.3.1 version: 18.3.1(react@18.3.1) uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing devDependencies: '@types/react': @@ -501,7 +501,7 @@ importers: specifier: 11.0.0-rc.452 version: 11.0.0-rc.452 '@uploadthing/expo': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../packages/expo expo: specifier: ~51.0.8 @@ -564,7 +564,7 @@ importers: specifier: ~0.19.12 version: 0.19.12(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing zod: specifier: ^3.23.8 @@ -589,13 +589,13 @@ importers: examples/minimal-nuxt: dependencies: '@uploadthing/nuxt': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../packages/nuxt nuxt: specifier: ^3.11.2 version: 3.11.2(@parcel/watcher@2.4.1)(@types/node@22.7.5)(encoding@0.1.13)(eslint@8.57.0)(ioredis@5.3.2)(lightningcss@1.24.1)(magicast@0.3.5)(optionator@0.9.3)(rollup@4.24.0)(terser@5.34.1)(typescript@5.6.2)(vite@5.4.8(@types/node@22.7.5)(lightningcss@1.24.1)(terser@5.34.1))(vue-tsc@2.0.14(typescript@5.6.2))(webpack-sources@3.2.3) uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing vue: specifier: ^3.4.21 @@ -607,7 +607,7 @@ importers: examples/minimal-pagedir: dependencies: '@uploadthing/react': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../packages/react next: specifier: 14.2.11 @@ -619,7 +619,7 @@ importers: specifier: 18.3.1 version: 18.3.1(react@18.3.1) uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing devDependencies: '@types/node': @@ -647,13 +647,13 @@ importers: specifier: ^1.0.6 version: 1.0.6(@testing-library/jest-dom@6.4.8)(rollup@4.24.0)(solid-js@1.8.23)(vinxi@0.4.3(@types/node@22.7.5)(encoding@0.1.13)(ioredis@5.3.2)(lightningcss@1.24.1)(magicast@0.3.5)(terser@5.34.1)(webpack-sources@3.2.3))(vite@5.4.8(@types/node@22.7.5)(lightningcss@1.24.1)(terser@5.34.1)) '@uploadthing/solid': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../packages/solid solid-js: specifier: ^1.8.23 version: 1.8.23 uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing vinxi: specifier: ^0.4.3 @@ -675,10 +675,10 @@ importers: specifier: ^5.0.17 version: 5.0.18 '@uploadthing/svelte': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../packages/svelte uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing devDependencies: '@sveltejs/adapter-auto': @@ -715,7 +715,7 @@ importers: specifier: ^1.69.3 version: 1.69.3(@types/node@22.7.5)(encoding@0.1.13)(ioredis@5.3.2)(lightningcss@1.24.1)(magicast@0.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(terser@5.34.1)(vite@5.4.8(@types/node@22.7.5)(lightningcss@1.24.1)(terser@5.34.1))(webpack-sources@3.2.3)(webpack@5.94.0) '@uploadthing/react': - specifier: ^7.0.3 + specifier: ^7.1.0 version: link:../../packages/react react: specifier: 18.3.1 @@ -724,7 +724,7 @@ importers: specifier: 18.3.1 version: 18.3.1(react@18.3.1) uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing vinxi: specifier: ^0.4.3 @@ -852,7 +852,7 @@ importers: specifier: ^0.10.1 version: 0.10.1(typescript@5.6.2)(zod@3.23.8) '@uploadthing/react': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../packages/react next: specifier: 14.2.11 @@ -864,7 +864,7 @@ importers: specifier: 18.3.1 version: 18.3.1(react@18.3.1) uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing zod: specifier: ^3.23.8 @@ -907,7 +907,7 @@ importers: specifier: ^0.10.1 version: 0.10.1(typescript@5.6.2)(zod@3.23.8) '@uploadthing/react': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../packages/react next: specifier: 14.2.11 @@ -919,7 +919,7 @@ importers: specifier: 18.3.1 version: 18.3.1(react@18.3.1) uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing zod: specifier: ^3.23.8 @@ -968,7 +968,7 @@ importers: specifier: ^2.12.0 version: 2.12.0(typescript@5.6.2) '@uploadthing/react': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../packages/react isbot: specifier: ^4.1.0 @@ -980,7 +980,7 @@ importers: specifier: 18.3.1 version: 18.3.1(react@18.3.1) uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing devDependencies: '@remix-run/dev': @@ -1020,7 +1020,7 @@ importers: specifier: ^0.10.1 version: 0.10.1(typescript@5.6.2)(zod@3.23.8) '@uploadthing/react': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../packages/react drizzle-orm: specifier: ^0.30.10 @@ -1035,7 +1035,7 @@ importers: specifier: 18.3.1 version: 18.3.1(react@18.3.1) uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing zod: specifier: ^3.23.8 @@ -1081,7 +1081,7 @@ importers: specifier: ^0.10.1 version: 0.10.1(typescript@5.6.2)(zod@3.23.8) '@uploadthing/react': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../packages/react drizzle-orm: specifier: ^0.30.10 @@ -1099,7 +1099,7 @@ importers: specifier: ^2.2.5 version: 2.2.5(react@18.3.1) uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing zod: specifier: ^3.23.8 @@ -1151,7 +1151,7 @@ importers: specifier: ^0.5.10 version: 0.5.13(tailwindcss@3.4.3) '@uploadthing/react': - specifier: ^7.0.3 + specifier: ^7.1.0 version: link:../../packages/react class-variance-authority: specifier: ^0.7.0 @@ -1184,7 +1184,7 @@ importers: specifier: ^2.2.1 version: 2.3.0 uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing use-debounce: specifier: ^9.0.3 @@ -1212,7 +1212,7 @@ importers: examples/with-react-image-crop: dependencies: '@uploadthing/react': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../packages/react next: specifier: 14.2.11 @@ -1227,7 +1227,7 @@ importers: specifier: ^11.0.5 version: 11.0.5(react@18.3.1) uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing devDependencies: '@types/node': @@ -1255,7 +1255,7 @@ importers: specifier: 18.3.1 version: 18.3.1(react@18.3.1) uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing devDependencies: '@types/node': @@ -1274,7 +1274,7 @@ importers: examples/with-tailwindcss: dependencies: '@uploadthing/react': - specifier: 7.0.3 + specifier: 7.1.0 version: link:../../packages/react next: specifier: 14.2.11 @@ -1286,7 +1286,7 @@ importers: specifier: 18.3.1 version: 18.3.1(react@18.3.1) uploadthing: - specifier: 7.1.0 + specifier: 7.2.0 version: link:../../packages/uploadthing devDependencies: '@types/node': @@ -5668,9 +5668,11 @@ packages: '@scalar/snippetz-core@0.1.4': resolution: {integrity: sha512-NMnDzl5dHgUj0k8ZtfssDfy6wv1wO/M+GhpdGr/4OH3m8UZB27CZ3hM7wXh+fm75hZO5XIBsANW20kJVnzpaHg==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. '@scalar/snippetz-plugin-js-fetch@0.1.1': resolution: {integrity: sha512-9ODfi0OaEvZHdCe09c91eH1R5QPynL+FPxtYuK/9K5ElRE2NqxYysri9AsgOhr1Fqhpy5qKzDj4Gi5FHsJSGXw==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. '@scalar/snippetz-plugin-js-ofetch@0.1.1': resolution: {integrity: sha512-fPIJlY4q1j5gbnsYSxix0IJ7hqcvm8Ly7iVoK66vaL738AIMiGZMhGKtLrTVPad77PimwO+jeq5iDIZ495UY7Q==} @@ -5678,6 +5680,7 @@ packages: '@scalar/snippetz-plugin-node-fetch@0.1.2': resolution: {integrity: sha512-kD6erA6aAqjHkj+JrJQKqrqcH4fnCrLi2uYw16CmELIGtqVHFau7ew2c087y4OQTltdi5rEk2zj5zOBu9yaS3Q==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. '@scalar/snippetz-plugin-node-ofetch@0.1.1': resolution: {integrity: sha512-9NpvdMKebg82FkVWoWyOxd1JXAB8KNxmrsFFwQKNjhAw0A5hjNR5oW9lD+FtB1Laupg2FNtw9dcCydnF+LcCWw==} @@ -5685,6 +5688,7 @@ packages: '@scalar/snippetz-plugin-node-undici@0.1.6': resolution: {integrity: sha512-CivUl7wgZ6vlUb01FMdqOt/NVyOWqT0iHZRp5YlPp1pflXZLnAyi5antUTtBEUHUtHM2EO/WR7vx4kRsPcrgLg==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. '@scalar/snippetz@0.1.6': resolution: {integrity: sha512-z3DEpT/FIZq9yeHL/tz2v6WvdHIiZ4uvK96RdeTPKUUJ0IXvA5vONG3PF5LE0Q/408PCzWsZpGs9f97ztaeJSQ==} @@ -13960,6 +13964,7 @@ packages: shikiji-core@0.9.19: resolution: {integrity: sha512-AFJu/vcNT21t0e6YrfadZ+9q86gvPum6iywRyt1OtIPjPFe25RQnYJyxHQPMLKCCWA992TPxmEmbNcOZCAJclw==} + deprecated: Shikiji is merged back to Shiki v1.0, please migrate over to get the latest updates shikiji@0.9.19: resolution: {integrity: sha512-Kw2NHWktdcdypCj1GkKpXH4o6Vxz8B8TykPlPuLHOGSV8VkhoCLcFOH4k19K4LXAQYRQmxg+0X/eM+m2sLhAkg==} From bb3054ff480d13edad13680cebd03957a611c4c1 Mon Sep 17 00:00:00 2001 From: juliusmarminge Date: Mon, 28 Oct 2024 09:52:12 +0100 Subject: [PATCH 11/15] add ppr callout for next plugin --- .../(docs)/getting-started/appdir/page.mdx | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/src/app/(docs)/getting-started/appdir/page.mdx b/docs/src/app/(docs)/getting-started/appdir/page.mdx index d095074fab..1a488d3578 100644 --- a/docs/src/app/(docs)/getting-started/appdir/page.mdx +++ b/docs/src/app/(docs)/getting-started/appdir/page.mdx @@ -233,6 +233,37 @@ export default function RootLayout({ } ``` + + +If using the experimental `ppr` or `dynamicIO` features in Next.js 15, wrap the +`` in suspense and call `await connection()` before rendering +the component. + +```tsx {{title: "app/layout.tsx" }} +import { connnection } from "next/server"; // [!code ++] +import { Suspense } from "react"; // [!code ++] + +async function UTSSR() { + await connection(); // [!code ++] + + return +} + +export default function RootLayout(props) { + return ( + + {...} + // [!code ++] + + // [!code ++] + {...} + + ) +} +``` + + + --- ### 🎉 You're Done! From 1b23106bfdbeb0c06d21034ef13e5307ec833580 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Tue, 29 Oct 2024 22:19:43 +0100 Subject: [PATCH 12/15] docs: add callouts and examples for keygen in other languages (#1035) Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- docs/src/app/(docs)/uploading-files/page.mdx | 168 ++++++++++++++++++- docs/src/mdx/rehype.js | 2 + 2 files changed, 166 insertions(+), 4 deletions(-) diff --git a/docs/src/app/(docs)/uploading-files/page.mdx b/docs/src/app/(docs)/uploading-files/page.mdx index 856d6a1588..28217b5662 100644 --- a/docs/src/app/(docs)/uploading-files/page.mdx +++ b/docs/src/app/(docs)/uploading-files/page.mdx @@ -102,6 +102,20 @@ The file seed can be anything you want, but it should be unique for each file, as well as url safe. In this example, we include a base64 encoding to ensure the file seed is url safe, but you can do this however you want. +Although we currently only offer a JavaScript SDK, here are some reference +implementations you can use to generate valid file keys. We also plan on making +this process easier in the future. + + + If you struggle to implement it for your language, you can also request one + from the [`/v7/prepareUpload` REST + endpoint](/api-reference/openapi-spec#tag/default/POST/v7/prepareUpload). Keep + in mind that this adds extra latency to your uploads. + + + + + ```ts import * as Hash from "effect/Hash"; import SQIds, { defaultOptions } from "sqids"; @@ -123,10 +137,7 @@ function shuffle(str: string, seed: string) { return chars.join(""); } -function generateKey( - appId: string, - fileSeed: string, -) => +function generateKey(appId: string, fileSeed: string) { // Hash and Encode the parts and apiKey as sqids const alphabet = shuffle(defaultOptions.alphabet, appId); @@ -142,6 +153,155 @@ function generateKey( } ``` + + + +```py +import math +import base64 +from sqids import Sqids +from sqids.constants import DEFAULT_ALPHABET + +def hash_string(s: str) -> int: + h = 5381 + for char in reversed(s): + h = (h * 33) ^ ord(char) + # 32-bit integer overflow + h &= 0xFFFFFFFF + h = (h & 0xBFFFFFFF) | ((h >> 1) & 0x40000000) + + # Convert to signed 32-bit integer + if h >= 0x80000000: + h -= 0x100000000 + + return h + + +def shuffle(string: str, seed: str) -> str: + chars = list(string) + seed_num = hash_string(seed) + + for i in range(len(chars)): + j = int(math.fmod(math.fmod(seed_num, i + 1) + i, len(chars))) + chars[i], chars[j] = chars[j], chars[i] + + return "".join(chars) + + +def generate_key(file_seed: str, app_id: str) -> str: + alphabet = shuffle(DEFAULT_ALPHABET, app_id) + + encoded_app_id = Sqids(alphabet, min_length=12).encode( + [abs(hash_string(app_id))] + ) + + return encoded_app_id + file_seed +``` + + + + +```php +use Sqids\Sqids; + +function hash_string(string $string): int { + $h = 5381; + for ($i = strlen($string) - 1; $i >= 0; $i--) { + $char = $string[$i]; + $h = ($h * 33) ^ ord($char); + // 32-bit integer overflow + $h &= 0xFFFFFFFF; + } + $h = ($h & 0xBFFFFFFF) | (($h >> 1) & 0x40000000); + + // Convert to signed 32-bit integer + if ($h >= 0x80000000) { + $h -= 0x100000000; + } + + return $h; + } + +function shuffle_string(string $string, string $seed): string { + $chars = str_split($string); + $seed_num = hash_string($seed); + + for ($i = 0; $i < count($chars); $i++) { + $j = (($seed_num % ($i + 1)) + $i) % count($chars); + [$chars[$i], $chars[$j]] = [$chars[$j], $chars[$i]]; + } + + return implode('', $chars); +} + +function generate_key(string $file_seed, string $appId): string { + $alphabet = shuffle_string(Sqids::DEFAULT_ALPHABET, $appId); + $sqids = new Sqids($alphabet, 12); + + $encodedAppId = $sqids->encode( + [abs(hash_string($appId))] + ); + + return $encodedAppId . base64_encode($file_seed); +} +``` + + + + +```go +import ( + "math" + "github.com/sqids/sqids-go" +) + +func hashString(s string) int32 { + h := int64(5381) + for i := len(s) - 1; i >= 0; i-- { + h = (h * 33) ^ int64(s[i]) + // 32-bit integer overflow + h &= 0xFFFFFFFF + } + h = (h & 0xBFFFFFFF) | ((h >> 1) & 0x40000000) + + // Convert to signed 32-bit integer + if h >= 0x80000000 { + h -= 0x100000000 + } + + return int32(h) +} + +func shuffle(input string, seed string) string { + chars := []rune(input) + seedNum := hashString(seed) + + for i := 0; i < len(chars); i++ { + j := (int(seedNum)%(i+1) + i) % len(chars) + chars[i], chars[j] = chars[j], chars[i] + } + + return string(chars) +} + +func generateKey(fileSeed string, appId string) string { + alphabet := shuffle("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", appId) + s, _ := sqids.New(sqids.Options{ + MinLength: 12, + Alphabet: alphabet, + }) + + encodedAppId, _ := s.Encode( + []uint64{uint64(math.Abs(float64(hashString(appId))))}, + ) + + return encodedAppId + fileSeed +} +``` + + + + The URL, to which you will upload the file, will depend on your app's region. You can find the list of regions in the [regions documentation](/concepts/regions-acl#regions). The upload URL can then diff --git a/docs/src/mdx/rehype.js b/docs/src/mdx/rehype.js index 8f50e76693..cb8cda711d 100644 --- a/docs/src/mdx/rehype.js +++ b/docs/src/mdx/rehype.js @@ -37,6 +37,8 @@ function rehypeShiki() { "css", "python", "diff", + "go", + "php", ], }); From d98fbefedddf64d183cc5a00b3fd707e8d8f2f6c Mon Sep 17 00:00:00 2001 From: Ibrahim Amin <58993233+notEpsilon@users.noreply.github.com> Date: Mon, 4 Nov 2024 09:44:24 +0200 Subject: [PATCH 13/15] fix(docs): typo in getting-started/appdir docs (#1038) --- docs/src/app/(docs)/getting-started/appdir/page.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/app/(docs)/getting-started/appdir/page.mdx b/docs/src/app/(docs)/getting-started/appdir/page.mdx index 1a488d3578..72a8a0abb4 100644 --- a/docs/src/app/(docs)/getting-started/appdir/page.mdx +++ b/docs/src/app/(docs)/getting-started/appdir/page.mdx @@ -240,7 +240,7 @@ If using the experimental `ppr` or `dynamicIO` features in Next.js 15, wrap the the component. ```tsx {{title: "app/layout.tsx" }} -import { connnection } from "next/server"; // [!code ++] +import { connection } from "next/server"; // [!code ++] import { Suspense } from "react"; // [!code ++] async function UTSSR() { From de98babde74323fca4e376779161d9d22edd1b0a Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Mon, 4 Nov 2024 23:58:17 +0100 Subject: [PATCH 14/15] fix: nuxt module tailwind support (#1033) --- .changeset/little-boxes-taste.md | 6 + packages/nuxt/package.json | 1 + packages/nuxt/playground/app.vue | 2 +- packages/nuxt/playground/nuxt.config.ts | 2 +- packages/nuxt/playground/package.json | 1 + packages/nuxt/src/module.ts | 75 ++- packages/uploadthing/src/tw.ts | 44 +- pnpm-lock.yaml | 805 +++++++++++++++++++++--- pnpm-workspace.yaml | 1 + 9 files changed, 837 insertions(+), 100 deletions(-) create mode 100644 .changeset/little-boxes-taste.md diff --git a/.changeset/little-boxes-taste.md b/.changeset/little-boxes-taste.md new file mode 100644 index 0000000000..0f30de4ad8 --- /dev/null +++ b/.changeset/little-boxes-taste.md @@ -0,0 +1,6 @@ +--- +"uploadthing": patch +"@uploadthing/nuxt": patch +--- + +fix: dynamically add either stylesheet or tailwind plugin based on whether `@nuxtjs/tailwindcss´ is installed diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index 06c774ef08..31a03b7950 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -36,6 +36,7 @@ "@nuxt/module-builder": "^0.5.5", "@nuxt/schema": "^3.11.2", "@nuxt/test-utils": "^3.12.0", + "@nuxtjs/tailwindcss": "^6.12.2", "@uploadthing/eslint-config": "workspace:*", "eslint": "^8.57.0", "h3": "^1.11.1", diff --git a/packages/nuxt/playground/app.vue b/packages/nuxt/playground/app.vue index 4121cd8612..321e83a5e3 100644 --- a/packages/nuxt/playground/app.vue +++ b/packages/nuxt/playground/app.vue @@ -1,5 +1,5 @@