From 2265451d4bc2d77f528ac067c914cfce45ec1b50 Mon Sep 17 00:00:00 2001 From: dswbx Date: Thu, 23 Jan 2025 10:59:33 +0100 Subject: [PATCH] added handy nextjs-plasmic-bknd functions --- packages/plasmic/package.json | 30 ++++- .../plasmic/src/components/data/BkndData.tsx | 4 +- packages/plasmic/src/nextjs/index.tsx | 125 ++++++++++++++++++ 3 files changed, 151 insertions(+), 8 deletions(-) create mode 100644 packages/plasmic/src/nextjs/index.tsx diff --git a/packages/plasmic/package.json b/packages/plasmic/package.json index 3a31a01..e7c9778 100644 --- a/packages/plasmic/package.json +++ b/packages/plasmic/package.json @@ -1,6 +1,6 @@ { "name": "@bknd/plasmic", - "version": "0.5.0", + "version": "0.5.1", "type": "module", "sideEffects": false, "scripts": { @@ -30,9 +30,13 @@ "@plasmicapp/host": ">=1.0.0", "@plasmicapp/loader-react": ">=1.0.0" }, + "optionalDependencies": { + "@plasmicapp/loader-nextjs": "^1.0.0" + }, "tsup": { "entry": [ - "src/index.ts" + "src/index.ts", + "src/nextjs/index.tsx" ], "minify": true, "clean": true, @@ -42,7 +46,11 @@ "@plasmicapp/host", "@plasmicapp/query", "@plasmicapp/loader-react", - "swr" + "@plasmicapp/loader-nextjs", + "swr", + "next", + "next/error", + "next/router" ], "format": [ "esm" @@ -54,9 +62,19 @@ "sourceMap": true, "outDir": "dist" }, - "types": "dist/index.d.ts", - "module": "dist/index.js", - "main": "dist/index.js", + "types": "./dist/index.d.ts", + "module": "./dist/index.js", + "main": "./dist/index.js", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + }, + "./nextjs": { + "types": "./dist/nextjs/index.d.ts", + "import": "./dist/nextjs/index.js" + } + }, "files": [ "dist", "README.md", diff --git a/packages/plasmic/src/components/data/BkndData.tsx b/packages/plasmic/src/components/data/BkndData.tsx index 7f43334..e2ffff2 100644 --- a/packages/plasmic/src/components/data/BkndData.tsx +++ b/packages/plasmic/src/components/data/BkndData.tsx @@ -6,7 +6,7 @@ import { } from "@plasmicapp/host"; import { usePlasmicQueryData } from "@plasmicapp/loader-react"; import { useApi, useEntityQuery } from "bknd/client"; -import type { RepoQuery } from "bknd/data"; +import type { RepoQueryIn } from "bknd/data"; // biome-ignore lint/style/useImportType: import React from "react"; import { usePlasmicBkndContext } from "../../contexts/BkndContext"; @@ -171,7 +171,7 @@ type ModeProps = { error?: React.ReactNode; empty?: React.ReactNode; entityId?: number; - query?: Partial; + query?: RepoQueryIn; }; const ModeFetch = ({ diff --git a/packages/plasmic/src/nextjs/index.tsx b/packages/plasmic/src/nextjs/index.tsx new file mode 100644 index 0000000..26a1c9e --- /dev/null +++ b/packages/plasmic/src/nextjs/index.tsx @@ -0,0 +1,125 @@ +import { + type ComponentRenderData, + type NextJsPlasmicComponentLoader, + PlasmicComponent, + PlasmicRootProvider, + extractPlasmicQueryData +} from "@plasmicapp/loader-nextjs"; +import type { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from "next"; +import NextjsError from "next/error"; +import { useRouter } from "next/router"; +import React from "react"; + +type TPlasmic = NextJsPlasmicComponentLoader; +export type TGetStaticPropsOptions = { + baseUrl?: string; + revalidate?: number | boolean; +}; + +export function plasmicNextjsStatic(PLASMIC: TPlasmic, opts?: TGetStaticPropsOptions) { + return { + getStaticPaths: getStaticPaths(PLASMIC), + getStaticProps: getStaticProps(PLASMIC, opts), + CatchallPage: CatchallPage(PLASMIC) + }; +} + +export function getStaticPaths(PLASMIC: TPlasmic): GetStaticPaths { + return async () => { + const pages = await PLASMIC.fetchPages(); + return { + paths: pages.map((page) => ({ + params: { catchall: page.path.substring(1).split("/") } + })), + fallback: "blocking" + }; + }; +} + +export function getStaticProps(PLASMIC: TPlasmic, opts?: TGetStaticPropsOptions): GetStaticProps { + return async (context: GetStaticPropsContext) => { + const baseUrl = opts?.baseUrl ?? process.env.BASE_URL!; + + let { catchall } = context.params ?? {}; + if (catchall && Array.isArray(catchall) && catchall[0] === "index") { + console.log("setting catch all to undefined"); + catchall = undefined; + } + + const globalContextsProps = { + bkndContextProps: { + baseUrl + } + }; + + // Convert the catchall param into a path string + const plasmicPath = + typeof catchall === "string" + ? catchall + : catchall !== null && Array.isArray(catchall) + ? `/${catchall.join("/")}` + : "/"; + + const plasmicData = await PLASMIC.maybeFetchComponentData(plasmicPath); + if (!plasmicData) { + // This is some non-Plasmic catch-all page + return { + props: {} + }; + } + + // This is a path that Plasmic knows about. + const pageMeta = plasmicData.entryCompMetas[0]; + + // Cache the necessary data fetched for the page. + const queryCache = await extractPlasmicQueryData( + + + + ); + + const props = { plasmicData, queryCache, globalContextsProps }; + + // Pass the data in as props. + return { + props, + // Using incremental static regeneration, will invalidate this page + // after 300s (no deploy webhooks needed) + revalidate: opts?.revalidate ?? 300 + }; + }; +} + +export function CatchallPage(PLASMIC: TPlasmic) { + return (props: { + plasmicData?: ComponentRenderData; + queryCache?: Record; + globalContextsProps?: any; + }) => { + const { plasmicData, queryCache, globalContextsProps } = props; + const router = useRouter(); + if (!plasmicData || plasmicData.entryCompMetas.length === 0) { + return ; + } + const pageMeta = plasmicData.entryCompMetas[0]; + return ( + + + + ); + }; +}