mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
updated adapters to automatically verify auth
This commit is contained in:
@@ -13,11 +13,13 @@ export type Options = {
|
|||||||
host?: string;
|
host?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getApi(Astro: TAstro, options: Options = { mode: "static" }) {
|
export async function getApi(Astro: TAstro, options: Options = { mode: "static" }) {
|
||||||
return new Api({
|
const api = new Api({
|
||||||
host: new URL(Astro.request.url).origin,
|
host: new URL(Astro.request.url).origin,
|
||||||
headers: options.mode === "dynamic" ? Astro.request.headers : undefined
|
headers: options.mode === "dynamic" ? Astro.request.headers : undefined
|
||||||
});
|
});
|
||||||
|
await api.verifyAuth();
|
||||||
|
return api;
|
||||||
}
|
}
|
||||||
|
|
||||||
let app: App;
|
let app: App;
|
||||||
|
|||||||
@@ -29,8 +29,10 @@ export function createApi({ req }: GetServerSidePropsContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function withApi<T>(handler: (ctx: GetServerSidePropsContext & { api: Api }) => T) {
|
export function withApi<T>(handler: (ctx: GetServerSidePropsContext & { api: Api }) => T) {
|
||||||
return (ctx: GetServerSidePropsContext & { api: Api }) => {
|
return async (ctx: GetServerSidePropsContext & { api: Api }) => {
|
||||||
return handler({ ...ctx, api: createApi(ctx) });
|
const api = createApi(ctx);
|
||||||
|
await api.verifyAuth();
|
||||||
|
return handler({ ...ctx, api });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
import { useAuth } from "bknd/client";
|
||||||
import type { BkndAdminProps } from "bknd/ui";
|
import type { BkndAdminProps } from "bknd/ui";
|
||||||
import { Suspense, lazy, useEffect, useState } from "react";
|
import { Suspense, lazy, useEffect, useState } from "react";
|
||||||
|
|
||||||
export function adminPage(props?: BkndAdminProps) {
|
export function adminPage(props?: BkndAdminProps) {
|
||||||
const Admin = lazy(() => import("bknd/ui").then((mod) => ({ default: mod.Admin })));
|
const Admin = lazy(() => import("bknd/ui").then((mod) => ({ default: mod.Admin })));
|
||||||
return () => {
|
return () => {
|
||||||
|
const auth = useAuth();
|
||||||
const [loaded, setLoaded] = useState(false);
|
const [loaded, setLoaded] = useState(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof window === "undefined") return;
|
if (typeof window === "undefined") return;
|
||||||
@@ -13,7 +15,7 @@ export function adminPage(props?: BkndAdminProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<Admin {...props} />
|
<Admin withProvider={{ user: auth.user }} {...props} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { type FrameworkBkndConfig, createFrameworkApp } from "adapter";
|
import { type FrameworkBkndConfig, createFrameworkApp } from "adapter";
|
||||||
import type { App } from "bknd";
|
import type { App } from "bknd";
|
||||||
|
import { Api } from "bknd/client";
|
||||||
|
|
||||||
export type RemixBkndConfig = FrameworkBkndConfig;
|
export type RemixBkndConfig = FrameworkBkndConfig;
|
||||||
|
|
||||||
@@ -12,3 +13,19 @@ export function serve(config: RemixBkndConfig = {}) {
|
|||||||
return app.fetch(args.request);
|
return app.fetch(args.request);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function withApi<Args extends { request: Request; context: { api: Api } }, R>(
|
||||||
|
handler: (args: Args, api: Api) => Promise<R>
|
||||||
|
) {
|
||||||
|
return async (args: Args) => {
|
||||||
|
if (!args.context.api) {
|
||||||
|
args.context.api = new Api({
|
||||||
|
host: new URL(args.request.url).origin,
|
||||||
|
headers: args.request.headers
|
||||||
|
});
|
||||||
|
await args.context.api.verifyAuth();
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler(args, args.context.api);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ import "bknd/dist/styles.css";
|
|||||||
|
|
||||||
import { getApi } from "bknd/adapter/astro";
|
import { getApi } from "bknd/adapter/astro";
|
||||||
|
|
||||||
const api = getApi(Astro, { mode: "dynamic" });
|
const api = await getApi(Astro, { mode: "dynamic" });
|
||||||
const user = api.getUser();
|
const user = api.getUser();
|
||||||
|
|
||||||
export const prerender = false;
|
export const prerender = false;
|
||||||
@@ -94,7 +94,7 @@ Here is an example of using the API in static context:
|
|||||||
```jsx
|
```jsx
|
||||||
---
|
---
|
||||||
import { getApi } from "bknd/adapter/astro";
|
import { getApi } from "bknd/adapter/astro";
|
||||||
const api = getApi(Astro);
|
const api = await getApi(Astro);
|
||||||
const { data } = await api.data.readMany("todos");
|
const { data } = await api.data.readMany("todos");
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ On SSR pages, you can also access the authenticated user:
|
|||||||
```jsx
|
```jsx
|
||||||
---
|
---
|
||||||
import { getApi } from "bknd/adapter/astro";
|
import { getApi } from "bknd/adapter/astro";
|
||||||
const api = getApi(Astro, { mode: "dynamic" });
|
const api = await getApi(Astro, { mode: "dynamic" });
|
||||||
const user = api.getUser();
|
const user = api.getUser();
|
||||||
const { data } = await api.data.readMany("todos");
|
const { data } = await api.data.readMany("todos");
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ Now make sure that you wrap your root layout with the `ClientProvider` so that a
|
|||||||
share the same context:
|
share the same context:
|
||||||
```tsx
|
```tsx
|
||||||
// app/root.tsx
|
// app/root.tsx
|
||||||
|
import { withApi } from "bknd/adapter/remix"
|
||||||
|
import { type Api, ClientProvider } from "bknd/client";
|
||||||
|
|
||||||
export function Layout(props) {
|
export function Layout(props) {
|
||||||
// nothing to change here, just for orientation
|
// nothing to change here, just for orientation
|
||||||
return (
|
return (
|
||||||
@@ -48,21 +51,12 @@ declare module "@remix-run/server-runtime" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// export a loader that initiates the API
|
// export a loader that initiates the API
|
||||||
// and pass it through the context
|
// and passes it down to args.context.api
|
||||||
export const loader = async (args: LoaderFunctionArgs) => {
|
export const loader = withApi(async (args: LoaderFunctionArgs, api: Api) => {
|
||||||
const api = new Api({
|
return {
|
||||||
host: new URL(args.request.url).origin,
|
user: api.getUser()
|
||||||
headers: args.request.headers
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// get the user from the API
|
|
||||||
const user = api.getUser();
|
|
||||||
|
|
||||||
// add api to the context
|
|
||||||
args.context.api = api;
|
|
||||||
|
|
||||||
return { user };
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const { user } = useLoaderData<typeof loader>();
|
const { user } = useLoaderData<typeof loader>();
|
||||||
@@ -93,15 +87,9 @@ Since the API has already been constructed in the root layout, you can now use i
|
|||||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||||
import { useLoaderData } from "@remix-run/react";
|
import { useLoaderData } from "@remix-run/react";
|
||||||
|
|
||||||
export const loader = async (args: LoaderFunctionArgs) => {
|
export const loader = async ({ context: { api } }: LoaderFunctionArgs) => {
|
||||||
const { api } = args.context;
|
|
||||||
|
|
||||||
// get the authenticated user
|
|
||||||
const user = api.getAuthState().user;
|
|
||||||
|
|
||||||
// get the data from the API
|
|
||||||
const { data } = await api.data.readMany("todos");
|
const { data } = await api.data.readMany("todos");
|
||||||
return { data, user };
|
return { data, user: api.getUser() };
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Index() {
|
export default function Index() {
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ import "bknd/dist/styles.css";
|
|||||||
|
|
||||||
import { getApi } from "bknd/adapter/astro";
|
import { getApi } from "bknd/adapter/astro";
|
||||||
|
|
||||||
const api = getApi(Astro, { mode: "dynamic" });
|
const api = await getApi(Astro, { mode: "dynamic" });
|
||||||
await api.verifyAuth();
|
|
||||||
const user = api.getUser();
|
const user = api.getUser();
|
||||||
|
|
||||||
export const prerender = false;
|
export const prerender = false;
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
import { getApi } from "bknd/adapter/astro";
|
import { getApi } from "bknd/adapter/astro";
|
||||||
import Card from "../components/Card.astro";
|
import Card from "../components/Card.astro";
|
||||||
import Layout from "../layouts/Layout.astro";
|
import Layout from "../layouts/Layout.astro";
|
||||||
const api = getApi(Astro);
|
|
||||||
|
const api = await getApi(Astro);
|
||||||
const { data } = await api.data.readMany("todos");
|
const { data } = await api.data.readMany("todos");
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
import { getApi } from "bknd/adapter/astro";
|
import { getApi } from "bknd/adapter/astro";
|
||||||
import Card from "../components/Card.astro";
|
import Card from "../components/Card.astro";
|
||||||
import Layout from "../layouts/Layout.astro";
|
import Layout from "../layouts/Layout.astro";
|
||||||
const api = getApi(Astro, { mode: "dynamic" });
|
const api = await getApi(Astro, { mode: "dynamic" });
|
||||||
await api.verifyAuth();
|
|
||||||
|
|
||||||
const { data } = await api.data.readMany("todos");
|
const { data } = await api.data.readMany("todos");
|
||||||
const user = api.getUser();
|
const user = api.getUser();
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||||
import { Links, Meta, Outlet, Scripts, ScrollRestoration, useLoaderData } from "@remix-run/react";
|
import { Links, Meta, Outlet, Scripts, ScrollRestoration, useLoaderData } from "@remix-run/react";
|
||||||
import { Api, ClientProvider } from "bknd/client";
|
import { withApi } from "bknd/adapter/remix";
|
||||||
|
import { type Api, ClientProvider } from "bknd/client";
|
||||||
declare module "@remix-run/server-runtime" {
|
|
||||||
export interface AppLoadContext {
|
|
||||||
api: Api;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Layout({ children }: { children: React.ReactNode }) {
|
export function Layout({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
@@ -26,20 +21,17 @@ export function Layout({ children }: { children: React.ReactNode }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const loader = async (args: LoaderFunctionArgs) => {
|
declare module "@remix-run/server-runtime" {
|
||||||
const api = new Api({
|
export interface AppLoadContext {
|
||||||
host: new URL(args.request.url).origin,
|
api: Api;
|
||||||
headers: args.request.headers
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
// add api to the context
|
export const loader = withApi(async (args: LoaderFunctionArgs, api: Api) => {
|
||||||
args.context.api = api;
|
|
||||||
|
|
||||||
await api.verifyAuth();
|
|
||||||
return {
|
return {
|
||||||
user: api.getAuthState()?.user
|
user: api.getUser()
|
||||||
};
|
};
|
||||||
};
|
});
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const data = useLoaderData<typeof loader>();
|
const data = useLoaderData<typeof loader>();
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
import { type MetaFunction, useLoaderData } from "@remix-run/react";
|
import { type MetaFunction, useLoaderData } from "@remix-run/react";
|
||||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||||
|
import { useAuth } from "bknd/client";
|
||||||
|
|
||||||
export const meta: MetaFunction = () => {
|
export const meta: MetaFunction = () => {
|
||||||
return [{ title: "Remix & bknd" }, { name: "description", content: "Welcome to Remix & bknd!" }];
|
return [{ title: "Remix & bknd" }, { name: "description", content: "Welcome to Remix & bknd!" }];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const loader = async (args: LoaderFunctionArgs) => {
|
export const loader = async ({ context: { api } }: LoaderFunctionArgs) => {
|
||||||
const api = args.context.api;
|
|
||||||
await api.verifyAuth();
|
|
||||||
const { data } = await api.data.readMany("todos");
|
const { data } = await api.data.readMany("todos");
|
||||||
return { data, user: api.getUser() };
|
return { data, user: api.getUser() };
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Index() {
|
export default function Index() {
|
||||||
const { data, user } = useLoaderData<typeof loader>();
|
const { data, user } = useLoaderData<typeof loader>();
|
||||||
|
const auth = useAuth();
|
||||||
|
console.log("auth", auth);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
Reference in New Issue
Block a user