mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 12:37:20 +00:00
updated nextjs example
This commit is contained in:
@@ -23,78 +23,97 @@ To get started with Next.js and bknd you can either install the package manually
|
||||
</Tabs>
|
||||
|
||||
## Serve the API
|
||||
``` tsx
|
||||
// pages/api/[...route].ts
|
||||
import { serve } from "bknd/adapter/nextjs";
|
||||
Create a helper file to instantiate the bknd instance and retrieve the API:
|
||||
|
||||
```ts src/bknd.ts
|
||||
import { type NextjsBkndConfig, getApp as getBkndApp } from "bknd/adapter/nextjs";
|
||||
import { headers } from "next/headers";
|
||||
|
||||
export const config = {
|
||||
runtime: "edge", // or "experimental-edge", depending on your nextjs version
|
||||
unstable_allowDynamic: ["**/*.js"]
|
||||
};
|
||||
|
||||
export default serve({
|
||||
connection: {
|
||||
url: process.env.DB_URL!,
|
||||
authToken: process.env.DB_AUTH_TOKEN!
|
||||
url: "file:data.db"
|
||||
},
|
||||
} as const satisfies NextjsBkndConfig;
|
||||
|
||||
export async function getApp() {
|
||||
return await getBkndApp(config);
|
||||
}
|
||||
|
||||
export async function getApi(opts?: { verify?: boolean }) {
|
||||
const app = await getApp();
|
||||
if (opts?.verify) {
|
||||
const api = app.getApi({ headers: await headers() });
|
||||
await api.verifyAuth();
|
||||
return api;
|
||||
}
|
||||
});
|
||||
|
||||
return app.getApi();
|
||||
}
|
||||
```
|
||||
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
||||
|
||||
Now to expose the API, create a catch-all route file at `src/api/[[...bknd]]/route.ts`:
|
||||
```ts src/api/[[...bknd]]/route.ts
|
||||
import { config } from "@/bknd";
|
||||
import { serve } from "bknd/adapter/nextjs";
|
||||
|
||||
// optionally, you can set the runtime to edge for better performance
|
||||
export const runtime = "edge";
|
||||
|
||||
const handler = serve({
|
||||
...config,
|
||||
cleanRequest: {
|
||||
// depending on what name you used for the catch-all route,
|
||||
// you need to change this to clean it from the request.
|
||||
searchParams: ["bknd"],
|
||||
},
|
||||
});
|
||||
|
||||
export const GET = handler;
|
||||
export const POST = handler;
|
||||
export const PUT = handler;
|
||||
export const PATCH = handler;
|
||||
export const DELETE = handler;
|
||||
```
|
||||
|
||||
## Enabling the Admin UI
|
||||
Create a file `[[...admin]].tsx` inside the `pages/admin` folder:
|
||||
```tsx
|
||||
// pages/admin/[[...admin]].tsx
|
||||
import type { InferGetServerSidePropsType as InferProps } from "next";
|
||||
import { withApi } from "bknd/adapter/nextjs";
|
||||
import dynamic from "next/dynamic";
|
||||
Create a page at `admin/[[...admin]]/page.tsx`:
|
||||
```tsx admin/[[...admin]]/page.tsx
|
||||
import { Admin } from "bknd/ui";
|
||||
import { getApi } from "@/bknd";
|
||||
import "bknd/dist/styles.css";
|
||||
|
||||
const Admin = dynamic(() => import("bknd/ui").then((mod) => mod.Admin), {
|
||||
ssr: false,
|
||||
});
|
||||
export default async function AdminPage() {
|
||||
// make sure to verify auth using headers
|
||||
const api = await getApi({ verify: true });
|
||||
|
||||
export const getServerSideProps = withApi(async (context) => {
|
||||
return {
|
||||
props: {
|
||||
user: context.api.getUser(),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export default function AdminPage({ user }: InferProps<typeof getServerSideProps>) {
|
||||
if (typeof document === "undefined") return null;
|
||||
return <Admin
|
||||
withProvider={{ user }}
|
||||
config={{ basepath: "/admin", logo_return_path: "/../" }}
|
||||
/>;
|
||||
return (
|
||||
<Admin
|
||||
withProvider={{ user: api.getUser() }}
|
||||
config={{
|
||||
basepath: "/admin",
|
||||
logo_return_path: "/../",
|
||||
color_scheme: "system",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Example usage of the API in pages dir
|
||||
Using pages dir, you need to wrap the `getServerSideProps` function with `withApi` to get access
|
||||
to the API. With the API, you can query the database or retrieve the authentication status:
|
||||
```tsx
|
||||
import { withApi } from "bknd/adapter/nextjs";
|
||||
import type { InferGetServerSidePropsType as InferProps } from "next";
|
||||
## Example usage of the API
|
||||
You can use the `getApi` helper function we've already set up to fetch and mutate in static pages and server components:
|
||||
|
||||
export const getServerSideProps = withApi(async (context) => {
|
||||
const { data = [] } = await context.api.data.readMany("todos");
|
||||
const user = context.api.getUser();
|
||||
```tsx app/page.tsx
|
||||
import { getApi } from "@/bknd";
|
||||
|
||||
return { props: { data, user } };
|
||||
});
|
||||
export default async function Home() {
|
||||
const api = await getApi();
|
||||
const { data: todos } = await api.data.readMany("todos", { limit: 5 });
|
||||
|
||||
export default function Home(props: InferProps<typeof getServerSideProps>) {
|
||||
const { data, user } = props;
|
||||
return (
|
||||
<div>
|
||||
<h1>Data</h1>
|
||||
<pre>{JSON.stringify(data, null, 2)}</pre>
|
||||
|
||||
<h1>User</h1>
|
||||
<pre>{JSON.stringify(user, null, 2)}</pre>
|
||||
</div>
|
||||
);
|
||||
return <ul>
|
||||
{todos.map((todo) => (
|
||||
<li key={String(todo.id)}>{todo.title}</li>
|
||||
))}
|
||||
</ul>
|
||||
}
|
||||
```
|
||||
@@ -24,7 +24,8 @@ To get started with Remix and bknd you can either install the package manually,
|
||||
|
||||
|
||||
## Serve the API
|
||||
Since Remix doesn't support middleware yet, we need a helper file to initialize the App to import from. Create a new file at `app/bknd.ts`:
|
||||
Create a helper file to instantiate the bknd instance and retrieve the API:
|
||||
|
||||
```ts app/bknd.ts
|
||||
import { type RemixBkndConfig, getApp as getBkndApp } from "bknd/adapter/remix";
|
||||
|
||||
@@ -49,6 +50,7 @@ export async function getApi(args?: { request: Request }) {
|
||||
return app.getApi();
|
||||
}
|
||||
```
|
||||
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
||||
|
||||
Create a new api splat route file at `app/routes/api.$.ts`:
|
||||
```ts app/routes/api.$.ts
|
||||
@@ -62,7 +64,6 @@ const handler = async (args: { request: Request }) => {
|
||||
export const loader = handler;
|
||||
export const action = handler;
|
||||
```
|
||||
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
||||
|
||||
Now make sure that you wrap your root layout with the `ClientProvider` so that all components share the same context. Also add the user context to both the `Outlet` and the provider:
|
||||
```tsx app/root.tsx
|
||||
|
||||
Reference in New Issue
Block a user