You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{"changes":{"packages/webpack-plugin/package.json":"Patch","packages/fetch/package.json":"Patch","packages/next-plugin/package.json":"Patch","packages/vite-plugin/package.json":"Patch","packages/rsbuild-plugin/package.json":"Patch","packages/core/package.json":"Patch","packages/utils/package.json":"Patch","packages/generator/package.json":"Patch"},"note":"Gen server code","date":"2026-04-27T20:38:10.725587800Z"}
@@ -64,6 +65,11 @@ devup-api feels like using `fetch`, but with superpowers:
64
65
- Automatic type generation during build time
65
66
- Zero runtime overhead
66
67
68
+
### **⚡ Generated Next.js Server Actions**
69
+
- Generate top-level Server Action functions from OpenAPI operationIds
70
+
- Import actions from `@devup-api/fetch/server` instead of reaching into `df`
71
+
- Cold typing works before generated files exist, then becomes fully typed after the plugin runs
72
+
67
73
---
68
74
69
75
## 🚀 Quick Start
@@ -714,6 +720,57 @@ type Product = DevupObject<'response', 'openapi2.json'>['Product'] // From open
714
720
715
721
---
716
722
723
+
## ⚡ Next.js Server Actions
724
+
725
+
devup-api generates named Server Action wrappers for operationId-based API calls by default. This is useful in Next.js App Router projects when you want to call server-side API functions from Client Components without manually writing one action per endpoint.
726
+
727
+
Set `serverActions.baseUrl` when generated actions should call a specific API origin:
728
+
729
+
```ts
730
+
// next.config.ts
731
+
importdevupApifrom'@devup-api/next-plugin'
732
+
733
+
exportdefaultdevupApi({
734
+
reactStrictMode: true,
735
+
serverActions: {
736
+
baseUrl: 'https://api.example.com',
737
+
},
738
+
})
739
+
```
740
+
741
+
Then import generated actions from the virtual server module:
742
+
743
+
```tsx
744
+
'use client'
745
+
746
+
import { getUser } from'@devup-api/fetch/server'
747
+
748
+
exportfunction UserButton() {
749
+
return (
750
+
<button
751
+
type="button"
752
+
onClick={async () => {
753
+
const result =awaitgetUser({ params: { id: '123' } })
754
+
console.log(result.data)
755
+
console.log(result.response.status)
756
+
}}
757
+
>
758
+
Load user
759
+
</button>
760
+
)
761
+
}
762
+
```
763
+
764
+
The generated `df/server.ts` file contains `'use server'` and exports one named async function for every operationId in your OpenAPI schemas. You should import from `@devup-api/fetch/server`, not from `df/server.ts` directly; the build plugin aliases that module to the generated file.
765
+
766
+
Generated actions return `DevupApiResponse<T, E, SerializedResponse>`. This keeps the same `data` / `error` / `isOk` / `isError` shape as normal `api.get()` calls, while replacing the native `Response` instance with a plain serializable response object that can cross the Server Action boundary.
767
+
768
+
During cold typing, `@devup-api/fetch/server` is still importable before `df` exists. The fallback keeps initial setup from failing, and the generated module replaces it with strict operation-specific types after `dev` or `build` runs.
769
+
770
+
Server Actions are enabled by default. Disable generation explicitly with `serverActions: false` or `serverActions: { enabled: false }`.
771
+
772
+
---
773
+
717
774
## 🔄 React Query Integration
718
775
719
776
devup-api provides first-class support for TanStack React Query through the `@devup-api/react-query` package. All hooks are fully typed based on your OpenAPI schema.
0 commit comments