next-suspend 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # next-suspend
2
+
3
+ ```
4
+ npm i next-suspend
5
+ ```
6
+
7
+ ## Getting started
8
+
9
+ ```tsx
10
+ import { suspend } from "next-suspend";
11
+
12
+ // 1. Setup your data resolver
13
+ export const SuspendedProduct = suspend(
14
+ async ({ productId }: { productId: string}) => {
15
+ const product = await db.select.productById({ productId });
16
+ if (!product) {
17
+ notFound();
18
+ }
19
+ return product;
20
+ },
21
+ );
22
+
23
+
24
+ // 2. Pass the params & render values suspensfully
25
+ export default async function Page({ params }: PageProps<"/inventory/[productId]">) {
26
+ return (
27
+ <div className="mb-8 w-full">
28
+ <Property icon={<TbGardenCart className="-mt-1 mr-1 size-6" />}>
29
+ <PropertyTitle>Product</PropertyTitle>
30
+ <PropertyValue>
31
+ <SuspendedProduct params={params} fallback={<SkeletonLine />}>
32
+ {({ name }) => <span>{name}</span>}
33
+ </SuspendedProduct>
34
+ </PropertyValue>
35
+ </Property>
36
+ <Property icon={<TbGardenCart className="-mt-1 mr-1 size-6" />}>
37
+ <PropertyTitle>Description</PropertyTitle>
38
+ <PropertyValue>
39
+ <SuspendedProduct params={params} fallback={<SkeletonLine />}>
40
+ {({ description }) => <span>{description}</span>}
41
+ </SuspendedProduct>
42
+ </PropertyValue>
43
+ </Property>
44
+ )
45
+ }
46
+ ```
47
+
48
+ Your resolver will run once per params.
49
+
50
+ ## Helper types
51
+
52
+ Simplify the data resolvers, so their params are typed by your routes:
53
+
54
+ ```ts
55
+ // 1. Define a global helper type
56
+ import type { AppRoutes } from "@/../.next/types/routes";
57
+
58
+ declare global {
59
+ type Suspended<Route extends AppRoutes> = Awaited<PageProps<Route>["params"]>;
60
+ }
61
+
62
+ // 2. Get params by Page
63
+ const SuspendedProduct = suspend(
64
+ async ({ productId }: Suspended<"/inventory/[productId]">) => {
65
+ // ...
66
+ },
67
+ );
68
+ ```
@@ -0,0 +1,7 @@
1
+ import { ReactNode, SuspenseProps } from "react";
2
+ //#region src/suspend.d.ts
3
+ export declare function suspend<Params extends Record<string, string>, Result>(resolve: (params: Params) => Promise<Result>): ({ params, children, ...props }: Omit<SuspenseProps, "children"> & {
4
+ params: Promise<Params>;
5
+ children: (props: Result) => ReactNode;
6
+ }) => Promise<import("react").JSX.Element>;
7
+ //#endregion
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ import{Suspense as e,cache as t}from"react";import{jsx as n}from"react/jsx-runtime";function r(r){let i=t(async e=>r(await e));return async function({params:t,children:r,...a}){return n(e,{...a,children:i(t).then(e=>r(e))})}}export{r as suspend};
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "next-suspend",
3
+ "version": "1.0.0",
4
+ "description": "Suspensfully access data by page params.",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "keywords": [
9
+ "react",
10
+ "nextjs",
11
+ "suspense",
12
+ "cache"
13
+ ],
14
+ "license": "ISC",
15
+ "author": "Miroslav Petrik",
16
+ "main": "dist/index.js",
17
+ "module": "dist/index.mjs",
18
+ "files": [
19
+ "/dist"
20
+ ],
21
+ "exports": {
22
+ ".": {
23
+ "import": "./dist/index.mjs",
24
+ "module": "./dist/index.mjs",
25
+ "types": "./dist/index.d.mts",
26
+ "default": "./dist/index.mjs"
27
+ }
28
+ },
29
+ "scripts": {
30
+ "build": "tsdown src/index.ts --minify"
31
+ },
32
+ "peerDependencies": {
33
+ "react": ">=19",
34
+ "react-dom": ">=19"
35
+ },
36
+ "devDependencies": {
37
+ "@types/react": "^19.2.18",
38
+ "@types/react-dom": "^19.2.7",
39
+ "react": "^19.2.8",
40
+ "react-dom": "^19.2.8",
41
+ "tsdown": "^0.23.0",
42
+ "typescript": "^7.0.2"
43
+ }
44
+ }