feat!: upgrade to Effect v4#1288
Conversation
Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
🦋 Changeset detectedLatest commit: 3a897cc The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
More templates
commit: |
📦 Bundle size comparison
|
…v4 exports Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
Summary
Upgrades the repo from Effect v3 (
effect@3.21.0+@effect/platform@0.96.0) to Effect v4 (effect@4.0.0-beta.93), following the migration guides in effect-TS/effect-smol (MIGRATION.mdandmigration/*.md, including the v3→v4 import/API rename maps and the Schema v4 guide).Live demo
End-to-end upload through
examples/backend-adaptersrunning the migrated stack against the live UploadThing API (sea1region): React client (UploadButton, migrated Effect v4 client code) → Effect v4HttpRouterserver (effect-platformadapter) → real presigned URL generation, ingest upload, dev-mode callback stream, andonUploadComplete:effect_v4_live_upload_demo.mp4
Upload complete alert after uploading through the Effect v4 stack
The server log confirmed the full dev-mode flow: metadata registered with the ingest server, callback forwarded from the dev stream with a valid
hmac-sha256signature,onUploadCompleteexecuted, and the callback result submitted (200). The live-API SDK surface (uploadFiles,uploadFilesFromUrl,generateSignedURL,getSignedURL,renameFiles,listFiles,deleteFiles) was also exercised against the real API viasdk.live.test.tsand a script using the built package output.Dependencies
effect3.21.0→4.0.0-beta.93(all workspaces)@effect/platformremoved — merged into coreeffectin v4; all HTTP modules now come fromeffect/unstable/http@effect/vitest0.29.0→4.0.0-beta.93,@effect/platform-node0.106.0→4.0.0-beta.93,@effect/language-service0.84.3→0.86.4.nvmrcbumped22.14→22.23:ini@7.0.0(transitive dep of effect v4) requires Node^22.22.2, sopnpm installfails its engine check on older Node 22 releasesexamples/minimal-exponow usesmoduleResolution: "bundler": effect v4 exposes submodules (e.g.effect/Schema) only through package.jsonexports(notypesVersionsfallback), which the legacynoderesolution fromexpo/tsconfig.basecannot follow@uploadthing/sharedeffect/Microwas removed in v4; client-side code now uses the coreEffectmodule (tree-shakeable in v4):Micro.TaggedError/Micro.Error→Data.TaggedError/Data.Error,Micro.withTrace→Effect.withSpan,Micro.async→Effect.callback,Micro.fromEither→Effect.fromResultContext.Tagclass →Context.ServiceforFetchContextPredicate.isRecord→Predicate.isObjectuploadthingclient.ts,client-future.ts,upload-browser.ts,ut-reporter.ts): Micro → Effect, interrupt detection viaCause.hasInterrupts,Cause.squashfor error unwrappingConfigProvider.fromJson→fromUnknown, customimport.meta.envfallback dropped (v4'sfromEnvmergesprocess.envandimport.meta.envnatively, built lazily to observe late env mutations),S.Config→Config.string+Schema.decodeUnknownEffectwith the sameMISSING_ENV/INVALID_SERVER_CONFIGerror semanticsLogLevelconfig validator replaced by v4'sConfig.logLevel(the code comment literally said "Effect 4.0 will change this... then we can remove this"), loggers set viaLogger.layer/References.MinimumLogLevel,HttpClientErrorreworked for the new single-class error withreason/responseFiberRef-based header redaction →Layer.effect(Headers.CurrentRedactedNames, ...); config provider merged into the runtime context viaLayer.provideMerge(v4 references live in the context, not fiber refs);Fetchservice falls back to a lazyglobalThis.fetchwrapper instead of overriding the reference withundefinedHttpRouter(removed in v4) replaced with method dispatch onHttpServerRequest;HttpApp.toWebHandlerRuntime→HttpEffect.toWebHandler+Effect.provideContext;Effect.forkDaemon→Effect.forkDetach,fiber.await→Fiber.await,Effect.ignoreLogged→ localignoreLoggedhelper,catchTag("ParseError")→catchTag("SchemaError")S.Literal(...xs)→S.Literals([...]),S.transform→S.decodeTo+SchemaTransformation.transform,S.optionalWith({ default })→S.withDecodingDefault(+withConstructorDefault),S.compose→S.decodeTo,S.parseJson→S.fromJsonString,S.Redacted→S.RedactedFromValue,S.startsWith→check(S.isStartsWith(...)),S.Record({key, value})→S.Record(key, value),Schema.Schema<A, I>→Schema.Codec<A, I>bodyUnsafeJson→bodyJsonUnsafe,Effect.tapBoth→tap/tapError,Effect.scopedon HTTP calls dropped (v4 responses are not scope-bound),ParseError→SchemaErrorEffect<HttpServerResponse, unknown, HttpClient | HttpServerRequest | Scope>usable with the v4 layer-basedHttpRouter(see updated example)Tests & tooling
Layer.setConfigProvider→ConfigProvider.layer,S.encode→S.encodeEffect,Stream.fromReadableStreamoptions object, updated v4 error shapes/messages)setImmediatestub (defined butundefined), which crashed Effect v4's scheduler feature detection in browser testsexamples/backend-adaptersEffect server rewritten to the v4 layer-based router; verified it boots and serves (GET /api,GET /api/uploadthing)majorforuploadthingand@uploadthing/shared)Testing
effect-platform(v4HttpRouter) server against the real UploadThing API, including dev-mode callbacks andserverDataround-trip; also verified via theexpressadapter andcurlsdk.live.test.tswith a real token): upload, upload-from-URL, rename by fileKey/customId, delete all pass; the remaining failures are app-tier assumptions baked into the suite (free-tierlimitBytes, ACL overrides disabled on the test app), not migration regressionspnpm test—@uploadthing/shared28 passed,uploadthing120 passed / 10 skipped (incl. chromium browser tests),@uploadthing/react16 passed / 1 skippedpnpm typecheck— all 37 tasks (packages + examples + playgrounds) successfulpnpm turbo run lint --filter "./packages/*"pnpm build— all 10 packages buildpnpm manypkg check,pnpm format:checkTo show artifacts inline, enable in settings.