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 +68 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.mjs +1 -0
- package/package.json +44 -0
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
|
+
```
|
package/dist/index.d.mts
ADDED
|
@@ -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
|
+
}
|