waku 1.0.0-beta.3 → 1.0.0-beta.4
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 +3 -3
- package/dist/lib/utils/prefetch-cache.d.ts +5 -10
- package/dist/lib/utils/prefetch-cache.js +6 -19
- package/dist/lib/utils/prefetch-cache.js.map +1 -1
- package/dist/lib/utils/rsc-stream.js +1 -1
- package/dist/lib/utils/rsc-stream.js.map +1 -1
- package/dist/minimal/client.d.ts +52 -19
- package/dist/minimal/client.js +135 -107
- package/dist/minimal/client.js.map +1 -1
- package/dist/router/client-utils/build-route-href.d.ts +26 -0
- package/dist/router/client-utils/build-route-href.js +61 -0
- package/dist/router/client-utils/build-route-href.js.map +1 -0
- package/dist/router/client-utils/match-route-params.d.ts +14 -0
- package/dist/router/client-utils/match-route-params.js +49 -0
- package/dist/router/client-utils/match-route-params.js.map +1 -0
- package/dist/router/client.d.ts +32 -25
- package/dist/router/client.js +39 -28
- package/dist/router/client.js.map +1 -1
- package/dist/router/{common.js → common-utils/route-path.js} +1 -3
- package/dist/router/common-utils/route-path.js.map +1 -0
- package/dist/router/create-pages-utils/inferred-path-types.d.ts +5 -5
- package/dist/router/create-pages-utils/inferred-path-types.js.map +1 -1
- package/dist/router/create-pages-utils/util-types.js.map +1 -0
- package/dist/router/create-pages.js +1 -1
- package/dist/router/create-pages.js.map +1 -1
- package/dist/router/define-router.js +1 -1
- package/dist/router/define-router.js.map +1 -1
- package/package.json +2 -2
- package/dist/router/common.js.map +0 -1
- package/dist/router/util-types.js.map +0 -1
- /package/dist/router/{common.d.ts → common-utils/route-path.d.ts} +0 -0
- /package/dist/router/{util-types.d.ts → create-pages-utils/util-types.d.ts} +0 -0
- /package/dist/router/{util-types.js → create-pages-utils/util-types.js} +0 -0
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ visit [waku.gg](https://waku.gg) or `npm create waku@latest`
|
|
|
17
17
|
|
|
18
18
|
## Getting started
|
|
19
19
|
|
|
20
|
-
Start a new Waku project with the `create` command for your preferred package manager. It will scaffold a new project with our default [Waku starter](https://github.com/wakujs/waku/tree/main/
|
|
20
|
+
Start a new Waku project with the `create` command for your preferred package manager. It will scaffold a new project with our default [Waku starter](https://github.com/wakujs/waku-examples/tree/main/fs-router/basic).
|
|
21
21
|
|
|
22
22
|
```sh
|
|
23
23
|
npm create waku@latest
|
|
@@ -804,11 +804,11 @@ export const Component = () => {
|
|
|
804
804
|
|
|
805
805
|
The `router` object also contains several methods for programmatic navigation:
|
|
806
806
|
|
|
807
|
-
- `router.push(to
|
|
807
|
+
- `router.push(to)` - navigate to the provided route. `to` is a route string, or a structured `{ to, params, search, hash }` target for typed navigation to dynamic routes (see [Typed Routes](https://github.com/wakujs/waku/blob/main/docs/guides/typed-routes.mdx))
|
|
808
808
|
|
|
809
809
|
- `router.prefetch(to: string)` - prefetch the provided route
|
|
810
810
|
|
|
811
|
-
- `router.replace(to
|
|
811
|
+
- `router.replace(to)` - replace the current history entry (same argument as `push`)
|
|
812
812
|
|
|
813
813
|
- `router.reload()` - reload the current route
|
|
814
814
|
|
|
@@ -5,16 +5,11 @@ export declare const PREFETCH_LIMIT = 100;
|
|
|
5
5
|
export type PrefetchEntry = {
|
|
6
6
|
rscPath: string;
|
|
7
7
|
rscParams: unknown;
|
|
8
|
-
|
|
8
|
+
elements: unknown;
|
|
9
9
|
expireAt: number;
|
|
10
10
|
};
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
* store: the prefetch's now, the navigation's after `consumePrefetchEntry`.
|
|
14
|
-
*/
|
|
15
|
-
export declare const addPrefetchEntry: <Store, Elements>(rscPath: string, rscParams: unknown, store: Store, decode: (getStore: () => Store) => Elements) => void;
|
|
11
|
+
/** Decode and cache a prefetch so a later navigation can reuse the tree. */
|
|
12
|
+
export declare const addPrefetchEntry: <Elements>(rscPath: string, rscParams: unknown, elements: Elements) => void;
|
|
16
13
|
export declare const hasPrefetchEntry: (rscPath: string, rscParams: unknown) => boolean;
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
*/
|
|
20
|
-
export declare const consumePrefetchEntry: <Store, Elements>(rscPath: string, rscParams: unknown, store: Store) => Elements | undefined;
|
|
14
|
+
/** Consume a fresh prefetch, returning its eagerly decoded tree. */
|
|
15
|
+
export declare const consumePrefetchEntry: <Elements>(rscPath: string, rscParams: unknown) => Elements | undefined;
|
|
@@ -1,30 +1,20 @@
|
|
|
1
1
|
// Client-side cache of prefetched navigations: a prefetch decodes the route
|
|
2
|
-
// eagerly so a later navigation reuses
|
|
3
|
-
//
|
|
4
|
-
// navigation's store, not the prefetch's. Bounded by a ttl and a max size.
|
|
2
|
+
// eagerly so a later navigation reuses the decoded tree without re-fetching.
|
|
3
|
+
// Bounded by a ttl and a max size.
|
|
5
4
|
/** How long (ms) a prefetched entry stays usable before it is discarded. */ export const PREFETCH_TTL = 1000 * 60;
|
|
6
5
|
/** Maximum number of prefetched entries kept at once. */ export const PREFETCH_LIMIT = 100;
|
|
7
6
|
const getCache = ()=>globalThis.__WAKU_PREFETCHED__ ||= [];
|
|
8
7
|
const findFreshIndex = (cache, rscPath, rscParams, now)=>cache.findIndex((entry)=>entry.expireAt > now && entry.rscPath === rscPath && // rscParams is intentionally compared by reference.
|
|
9
8
|
entry.rscParams === rscParams);
|
|
10
|
-
/**
|
|
11
|
-
* Decode and cache a prefetch. `getStore` returns the entry's currently bound
|
|
12
|
-
* store: the prefetch's now, the navigation's after `consumePrefetchEntry`.
|
|
13
|
-
*/ export const addPrefetchEntry = (rscPath, rscParams, store, decode)=>{
|
|
9
|
+
/** Decode and cache a prefetch so a later navigation can reuse the tree. */ export const addPrefetchEntry = (rscPath, rscParams, elements)=>{
|
|
14
10
|
const cache = getCache();
|
|
15
11
|
const now = Date.now();
|
|
16
|
-
let currentStore = store;
|
|
17
|
-
const elements = decode(()=>currentStore);
|
|
18
12
|
// Mark as handled so a prefetch that is never consumed stays quiet.
|
|
19
13
|
Promise.resolve(elements).catch(()=>{});
|
|
20
|
-
const getElements = (nextStore)=>{
|
|
21
|
-
currentStore = nextStore;
|
|
22
|
-
return elements;
|
|
23
|
-
};
|
|
24
14
|
cache.push({
|
|
25
15
|
rscPath,
|
|
26
16
|
rscParams,
|
|
27
|
-
|
|
17
|
+
elements,
|
|
28
18
|
expireAt: now + PREFETCH_TTL
|
|
29
19
|
});
|
|
30
20
|
while(cache.length > 0 && (cache.length > PREFETCH_LIMIT || cache[0].expireAt <= now)){
|
|
@@ -35,16 +25,13 @@ export const hasPrefetchEntry = (rscPath, rscParams)=>{
|
|
|
35
25
|
const cache = getCache();
|
|
36
26
|
return findFreshIndex(cache, rscPath, rscParams, Date.now()) >= 0;
|
|
37
27
|
};
|
|
38
|
-
/**
|
|
39
|
-
* Consume a fresh prefetch, rebinding its decoded tree to the consumer's store.
|
|
40
|
-
*/ export const consumePrefetchEntry = (rscPath, rscParams, store)=>{
|
|
28
|
+
/** Consume a fresh prefetch, returning its eagerly decoded tree. */ export const consumePrefetchEntry = (rscPath, rscParams)=>{
|
|
41
29
|
const cache = getCache();
|
|
42
30
|
const index = findFreshIndex(cache, rscPath, rscParams, Date.now());
|
|
43
31
|
if (index < 0) {
|
|
44
32
|
return undefined;
|
|
45
33
|
}
|
|
46
|
-
|
|
47
|
-
return getElements(store);
|
|
34
|
+
return cache.splice(index, 1)[0].elements;
|
|
48
35
|
};
|
|
49
36
|
|
|
50
37
|
//# sourceMappingURL=prefetch-cache.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/utils/prefetch-cache.ts"],"sourcesContent":["// Client-side cache of prefetched navigations: a prefetch decodes the route\n// eagerly so a later navigation reuses
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils/prefetch-cache.ts"],"sourcesContent":["// Client-side cache of prefetched navigations: a prefetch decodes the route\n// eagerly so a later navigation reuses the decoded tree without re-fetching.\n// Bounded by a ttl and a max size.\n\n/** How long (ms) a prefetched entry stays usable before it is discarded. */\nexport const PREFETCH_TTL = 1000 * 60;\n\n/** Maximum number of prefetched entries kept at once. */\nexport const PREFETCH_LIMIT = 100;\n\n// This is exported only for global-types.ts. It is not a public API.\nexport type PrefetchEntry = {\n rscPath: string;\n rscParams: unknown;\n elements: unknown;\n expireAt: number;\n};\n\nconst getCache = (): PrefetchEntry[] => (globalThis.__WAKU_PREFETCHED__ ||= []);\n\nconst findFreshIndex = (\n cache: PrefetchEntry[],\n rscPath: string,\n rscParams: unknown,\n now: number,\n) =>\n cache.findIndex(\n (entry) =>\n entry.expireAt > now &&\n entry.rscPath === rscPath &&\n // rscParams is intentionally compared by reference.\n entry.rscParams === rscParams,\n );\n\n/** Decode and cache a prefetch so a later navigation can reuse the tree. */\nexport const addPrefetchEntry = <Elements>(\n rscPath: string,\n rscParams: unknown,\n elements: Elements,\n): void => {\n const cache = getCache();\n const now = Date.now();\n // Mark as handled so a prefetch that is never consumed stays quiet.\n Promise.resolve(elements).catch(() => {});\n cache.push({ rscPath, rscParams, elements, expireAt: now + PREFETCH_TTL });\n while (\n cache.length > 0 &&\n (cache.length > PREFETCH_LIMIT || cache[0]!.expireAt <= now)\n ) {\n cache.shift();\n }\n};\n\nexport const hasPrefetchEntry = (\n rscPath: string,\n rscParams: unknown,\n): boolean => {\n const cache = getCache();\n return findFreshIndex(cache, rscPath, rscParams, Date.now()) >= 0;\n};\n\n/** Consume a fresh prefetch, returning its eagerly decoded tree. */\nexport const consumePrefetchEntry = <Elements>(\n rscPath: string,\n rscParams: unknown,\n): Elements | undefined => {\n const cache = getCache();\n const index = findFreshIndex(cache, rscPath, rscParams, Date.now());\n if (index < 0) {\n return undefined;\n }\n return cache.splice(index, 1)[0]!.elements as Elements;\n};\n"],"names":["PREFETCH_TTL","PREFETCH_LIMIT","getCache","globalThis","__WAKU_PREFETCHED__","findFreshIndex","cache","rscPath","rscParams","now","findIndex","entry","expireAt","addPrefetchEntry","elements","Date","Promise","resolve","catch","push","length","shift","hasPrefetchEntry","consumePrefetchEntry","index","undefined","splice"],"mappings":"AAAA,4EAA4E;AAC5E,6EAA6E;AAC7E,mCAAmC;AAEnC,0EAA0E,GAC1E,OAAO,MAAMA,eAAe,OAAO,GAAG;AAEtC,uDAAuD,GACvD,OAAO,MAAMC,iBAAiB,IAAI;AAUlC,MAAMC,WAAW,IAAwBC,WAAWC,mBAAmB,KAAK,EAAE;AAE9E,MAAMC,iBAAiB,CACrBC,OACAC,SACAC,WACAC,MAEAH,MAAMI,SAAS,CACb,CAACC,QACCA,MAAMC,QAAQ,GAAGH,OACjBE,MAAMJ,OAAO,KAAKA,WAClB,oDAAoD;QACpDI,MAAMH,SAAS,KAAKA;AAG1B,0EAA0E,GAC1E,OAAO,MAAMK,mBAAmB,CAC9BN,SACAC,WACAM;IAEA,MAAMR,QAAQJ;IACd,MAAMO,MAAMM,KAAKN,GAAG;IACpB,oEAAoE;IACpEO,QAAQC,OAAO,CAACH,UAAUI,KAAK,CAAC,KAAO;IACvCZ,MAAMa,IAAI,CAAC;QAAEZ;QAASC;QAAWM;QAAUF,UAAUH,MAAMT;IAAa;IACxE,MACEM,MAAMc,MAAM,GAAG,KACdd,CAAAA,MAAMc,MAAM,GAAGnB,kBAAkBK,KAAK,CAAC,EAAE,CAAEM,QAAQ,IAAIH,GAAE,EAC1D;QACAH,MAAMe,KAAK;IACb;AACF,EAAE;AAEF,OAAO,MAAMC,mBAAmB,CAC9Bf,SACAC;IAEA,MAAMF,QAAQJ;IACd,OAAOG,eAAeC,OAAOC,SAASC,WAAWO,KAAKN,GAAG,OAAO;AAClE,EAAE;AAEF,kEAAkE,GAClE,OAAO,MAAMc,uBAAuB,CAClChB,SACAC;IAEA,MAAMF,QAAQJ;IACd,MAAMsB,QAAQnB,eAAeC,OAAOC,SAASC,WAAWO,KAAKN,GAAG;IAChE,IAAIe,QAAQ,GAAG;QACb,OAAOC;IACT;IACA,OAAOnB,MAAMoB,MAAM,CAACF,OAAO,EAAE,CAAC,EAAE,CAAEV,QAAQ;AAC5C,EAAE"}
|
|
@@ -73,7 +73,7 @@ const collectFlightChunks = (root)=>{
|
|
|
73
73
|
};
|
|
74
74
|
export async function waitForRootPrerequisites(root) {
|
|
75
75
|
while(true){
|
|
76
|
-
const unresolvedChunks = collectFlightChunks(root).filter((chunk)=>isPendingStatus(chunk.status));
|
|
76
|
+
const unresolvedChunks = collectFlightChunks(root).filter((chunk)=>isPendingStatus(chunk.status) && typeof chunk.then === 'function');
|
|
77
77
|
if (unresolvedChunks.length === 0) {
|
|
78
78
|
return;
|
|
79
79
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/utils/rsc-stream.ts"],"sourcesContent":["type AnyFunction = (...args: unknown[]) => unknown;\n\ntype FlightChunk = {\n _children?: unknown;\n reason?: unknown;\n status: string;\n then?: AnyFunction;\n value?: unknown;\n};\n\ntype FlightRecordLike = {\n _children?: unknown;\n _payload?: unknown;\n handler?: { chunk?: unknown };\n props?: unknown;\n value?: unknown;\n};\n\nconst isObjectOrFunction = (value: unknown): value is object | AnyFunction =>\n value !== null && (typeof value === 'object' || typeof value === 'function');\n\nconst isFlightChunk = (value: unknown): value is FlightChunk =>\n isObjectOrFunction(value) &&\n 'status' in value &&\n typeof value.status === 'string' &&\n (!('then' in value) || typeof value.then === 'function');\n\nconst isFlightRecordLike = (value: unknown): value is FlightRecordLike =>\n isObjectOrFunction(value) &&\n (!('handler' in value) ||\n (isObjectOrFunction(value.handler) && 'chunk' in value.handler)) &&\n ('_payload' in value ||\n 'handler' in value ||\n '_children' in value ||\n 'value' in value ||\n 'props' in value);\n\nconst isPendingStatus = (value: string) =>\n value === 'pending' || value === 'blocked';\n\nconst pushInspectable = (stack: object[], value: unknown) => {\n if (isObjectOrFunction(value)) {\n stack.push(value);\n }\n};\n\nconst pushInspectableValues = (stack: object[], values: Iterable<unknown>) => {\n for (const value of values) {\n pushInspectable(stack, value);\n }\n};\n\nconst pushChunkEdges = (stack: object[], chunk: FlightChunk) => {\n if (Array.isArray(chunk._children)) {\n pushInspectableValues(stack, chunk._children);\n }\n pushInspectable(stack, chunk.value);\n pushInspectable(stack, chunk.reason);\n};\n\nconst pushRecordEdges = (stack: object[], record: FlightRecordLike) => {\n pushInspectable(stack, record._payload);\n if (record.handler) {\n pushInspectable(stack, record.handler.chunk);\n }\n if (Array.isArray(record._children)) {\n pushInspectableValues(stack, record._children);\n }\n pushInspectable(stack, record.value);\n pushInspectable(stack, record.props);\n};\n\nconst pushObjectValues = (stack: object[], value: object) => {\n pushInspectableValues(stack, Object.values(value));\n};\n\nconst collectFlightChunks = (root: unknown): FlightChunk[] => {\n const seen = new Set<object>();\n const chunks: FlightChunk[] = [];\n const stack: object[] = [];\n\n if (isObjectOrFunction(root)) {\n stack.push(root);\n }\n\n while (stack.length) {\n const value = stack.pop();\n if (!value || seen.has(value)) {\n continue;\n }\n seen.add(value);\n\n if (Array.isArray(value)) {\n pushInspectableValues(stack, value);\n continue;\n }\n if (value instanceof Map) {\n pushInspectableValues(stack, value.keys());\n pushInspectableValues(stack, value.values());\n continue;\n }\n if (value instanceof Set) {\n pushInspectableValues(stack, value.values());\n continue;\n }\n if (isFlightChunk(value)) {\n chunks.push(value);\n pushChunkEdges(stack, value);\n continue;\n }\n if (isFlightRecordLike(value)) {\n pushRecordEdges(stack, value);\n }\n pushObjectValues(stack, value);\n }\n return chunks;\n};\n\nexport async function waitForRootPrerequisites(root: unknown): Promise<void> {\n while (true) {\n const unresolvedChunks = collectFlightChunks(root).filter((chunk) =>\n
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils/rsc-stream.ts"],"sourcesContent":["type AnyFunction = (...args: unknown[]) => unknown;\n\ntype FlightChunk = {\n _children?: unknown;\n reason?: unknown;\n status: string;\n then?: AnyFunction;\n value?: unknown;\n};\n\ntype FlightRecordLike = {\n _children?: unknown;\n _payload?: unknown;\n handler?: { chunk?: unknown };\n props?: unknown;\n value?: unknown;\n};\n\nconst isObjectOrFunction = (value: unknown): value is object | AnyFunction =>\n value !== null && (typeof value === 'object' || typeof value === 'function');\n\nconst isFlightChunk = (value: unknown): value is FlightChunk =>\n isObjectOrFunction(value) &&\n 'status' in value &&\n typeof value.status === 'string' &&\n (!('then' in value) || typeof value.then === 'function');\n\nconst isFlightRecordLike = (value: unknown): value is FlightRecordLike =>\n isObjectOrFunction(value) &&\n (!('handler' in value) ||\n (isObjectOrFunction(value.handler) && 'chunk' in value.handler)) &&\n ('_payload' in value ||\n 'handler' in value ||\n '_children' in value ||\n 'value' in value ||\n 'props' in value);\n\nconst isPendingStatus = (value: string) =>\n value === 'pending' || value === 'blocked';\n\nconst pushInspectable = (stack: object[], value: unknown) => {\n if (isObjectOrFunction(value)) {\n stack.push(value);\n }\n};\n\nconst pushInspectableValues = (stack: object[], values: Iterable<unknown>) => {\n for (const value of values) {\n pushInspectable(stack, value);\n }\n};\n\nconst pushChunkEdges = (stack: object[], chunk: FlightChunk) => {\n if (Array.isArray(chunk._children)) {\n pushInspectableValues(stack, chunk._children);\n }\n pushInspectable(stack, chunk.value);\n pushInspectable(stack, chunk.reason);\n};\n\nconst pushRecordEdges = (stack: object[], record: FlightRecordLike) => {\n pushInspectable(stack, record._payload);\n if (record.handler) {\n pushInspectable(stack, record.handler.chunk);\n }\n if (Array.isArray(record._children)) {\n pushInspectableValues(stack, record._children);\n }\n pushInspectable(stack, record.value);\n pushInspectable(stack, record.props);\n};\n\nconst pushObjectValues = (stack: object[], value: object) => {\n pushInspectableValues(stack, Object.values(value));\n};\n\nconst collectFlightChunks = (root: unknown): FlightChunk[] => {\n const seen = new Set<object>();\n const chunks: FlightChunk[] = [];\n const stack: object[] = [];\n\n if (isObjectOrFunction(root)) {\n stack.push(root);\n }\n\n while (stack.length) {\n const value = stack.pop();\n if (!value || seen.has(value)) {\n continue;\n }\n seen.add(value);\n\n if (Array.isArray(value)) {\n pushInspectableValues(stack, value);\n continue;\n }\n if (value instanceof Map) {\n pushInspectableValues(stack, value.keys());\n pushInspectableValues(stack, value.values());\n continue;\n }\n if (value instanceof Set) {\n pushInspectableValues(stack, value.values());\n continue;\n }\n if (isFlightChunk(value)) {\n chunks.push(value);\n pushChunkEdges(stack, value);\n continue;\n }\n if (isFlightRecordLike(value)) {\n pushRecordEdges(stack, value);\n }\n pushObjectValues(stack, value);\n }\n return chunks;\n};\n\nexport async function waitForRootPrerequisites(root: unknown): Promise<void> {\n while (true) {\n const unresolvedChunks = collectFlightChunks(root).filter(\n (chunk) =>\n isPendingStatus(chunk.status) && typeof chunk.then === 'function',\n );\n if (unresolvedChunks.length === 0) {\n return;\n }\n await Promise.allSettled(unresolvedChunks);\n }\n}\n"],"names":["isObjectOrFunction","value","isFlightChunk","status","then","isFlightRecordLike","handler","isPendingStatus","pushInspectable","stack","push","pushInspectableValues","values","pushChunkEdges","chunk","Array","isArray","_children","reason","pushRecordEdges","record","_payload","props","pushObjectValues","Object","collectFlightChunks","root","seen","Set","chunks","length","pop","has","add","Map","keys","waitForRootPrerequisites","unresolvedChunks","filter","Promise","allSettled"],"mappings":"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"}
|
package/dist/minimal/client.d.ts
CHANGED
|
@@ -1,49 +1,82 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
type Elements = Record<string, unknown>;
|
|
3
|
-
type SetElements = (updater: (prev: Promise<Elements>) => Promise<Elements>) => void;
|
|
4
3
|
declare const ENTRY = "e";
|
|
5
4
|
declare const SET_ELEMENTS = "s";
|
|
6
|
-
declare const
|
|
5
|
+
declare const FETCH_ENHANCERS = "f";
|
|
7
6
|
declare const FETCH_RSC_INPUT_TRANSFORMERS = "t";
|
|
8
7
|
declare const CALL_SERVER_ELEMENTS_LISTENERS = "l";
|
|
9
|
-
|
|
10
|
-
type
|
|
11
|
-
type
|
|
8
|
+
type SetElements = (updater: (prev: Promise<Elements>) => Promise<Elements>) => void;
|
|
9
|
+
type FetchEnhancer = (fetchFn: typeof fetch) => typeof fetch;
|
|
10
|
+
type FetchEnhancers = Set<FetchEnhancer>;
|
|
11
|
+
type FetchRscInputTransformer = (rscPath: string, rscParams: unknown, prefetchOnly: boolean) => readonly [rscPath: string, rscParams: unknown, prefetchOnly: boolean];
|
|
12
|
+
type FetchRscInputTransformers = Set<FetchRscInputTransformer>;
|
|
12
13
|
type CallServerElementsListeners = Set<(elements: Elements) => void>;
|
|
13
|
-
type
|
|
14
|
+
type FetchRscStore = {
|
|
14
15
|
[ENTRY]?: [
|
|
15
16
|
rscPath: string,
|
|
16
17
|
rscParams: unknown,
|
|
17
18
|
elementsPromise: Promise<Elements>
|
|
18
19
|
];
|
|
19
20
|
[SET_ELEMENTS]?: SetElements;
|
|
20
|
-
[
|
|
21
|
+
[FETCH_ENHANCERS]?: FetchEnhancers;
|
|
21
22
|
[FETCH_RSC_INPUT_TRANSFORMERS]?: FetchRscInputTransformers;
|
|
22
23
|
[CALL_SERVER_ELEMENTS_LISTENERS]?: CallServerElementsListeners;
|
|
23
|
-
[ON_BUILD_ID_MISMATCH]?: () => void;
|
|
24
24
|
};
|
|
25
|
+
type FetchRscOptions = {
|
|
26
|
+
signal?: AbortSignal;
|
|
27
|
+
onBuildIdMismatch?: () => void;
|
|
28
|
+
};
|
|
29
|
+
type Refetch = (rscPath: string, rscParams?: unknown, options?: FetchRscOptions) => Promise<Elements>;
|
|
25
30
|
/**
|
|
26
31
|
* callServer callback
|
|
27
32
|
* This is not a public API.
|
|
28
33
|
*/
|
|
29
|
-
export declare const unstable_callServerRsc: (funcId: string, args: unknown[]
|
|
34
|
+
export declare const unstable_callServerRsc: (funcId: string, args: unknown[]) => Promise<unknown>;
|
|
30
35
|
type Unregister = () => void;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
export declare const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Register a listener that runs when a server action returns new elements.
|
|
38
|
+
* Returns a function that unregisters the listener.
|
|
39
|
+
*/
|
|
40
|
+
export declare const unstable_registerCallServerElementsListener: (listener: (elements: Elements) => void) => Unregister;
|
|
41
|
+
/**
|
|
42
|
+
* Register a fetch enhancer applied to every RSC request (e.g. to add headers).
|
|
43
|
+
* Enhancers are composed in registration order. Returns a function that
|
|
44
|
+
* unregisters the enhancer.
|
|
45
|
+
*/
|
|
46
|
+
export declare const unstable_registerFetchEnhancer: (enhance: FetchEnhancer) => Unregister;
|
|
47
|
+
/**
|
|
48
|
+
* Register a transformer that rewrites the RSC fetch input
|
|
49
|
+
* (`rscPath`, `rscParams`, `prefetchOnly`) before each request. Returns a
|
|
50
|
+
* function that unregisters the transformer.
|
|
51
|
+
*/
|
|
52
|
+
export declare function unstable_registerFetchRscInputTransformer(transformFetchRscInput: FetchRscInputTransformer): Unregister;
|
|
53
|
+
/**
|
|
54
|
+
* @deprecated Pass only the transformer. The store argument is ignored and this
|
|
55
|
+
* overload will be removed in a future release.
|
|
56
|
+
*/
|
|
57
|
+
export declare function unstable_registerFetchRscInputTransformer(store: FetchRscStore, transformFetchRscInput: FetchRscInputTransformer): Unregister;
|
|
58
|
+
/** Fetch elements for an RSC path, reusing a cached or prefetched result. */
|
|
59
|
+
export declare const unstable_fetchRsc: (rscPath: string, rscParams?: unknown, options?: FetchRscOptions) => Promise<Elements>;
|
|
60
|
+
/** Eagerly fetch and cache elements so a later fetch reuses them. */
|
|
61
|
+
export declare const unstable_prefetchRsc: (rscPath: string, rscParams?: unknown) => void;
|
|
62
|
+
/**
|
|
63
|
+
* Client root. Seeds the initial elements, bridges the store to React state,
|
|
64
|
+
* and provides the elements to `Slot` descendants.
|
|
65
|
+
*/
|
|
66
|
+
export declare const Root: ({ initialRscPath, initialRscParams, children, }: {
|
|
39
67
|
initialRscPath?: string;
|
|
40
68
|
initialRscParams?: unknown;
|
|
41
|
-
unstable_fetchRscStore?: Unstable_FetchRscStore | undefined;
|
|
42
69
|
children: ReactNode;
|
|
43
70
|
}) => import("react").JSX.Element;
|
|
44
|
-
export declare const useRefetch: () =>
|
|
71
|
+
export declare const useRefetch: () => Refetch;
|
|
45
72
|
export declare const Children: () => ReactNode;
|
|
46
73
|
export declare const useElementsPromise_UNSTABLE: () => Promise<Elements>;
|
|
74
|
+
/**
|
|
75
|
+
* @deprecated The store is an internal singleton; you no longer need to pass it
|
|
76
|
+
* to `unstable_registerFetchRscInputTransformer`. This will be removed in a
|
|
77
|
+
* future release.
|
|
78
|
+
*/
|
|
79
|
+
export declare const useFetchRscStore_UNSTABLE: () => FetchRscStore;
|
|
47
80
|
/**
|
|
48
81
|
* Slot component
|
|
49
82
|
* This is used under the Root component.
|
package/dist/minimal/client.js
CHANGED
|
@@ -57,70 +57,88 @@ const mergeElementsPromise = (a, b)=>{
|
|
|
57
57
|
};
|
|
58
58
|
const ENTRY = 'e';
|
|
59
59
|
const SET_ELEMENTS = 's';
|
|
60
|
-
const
|
|
60
|
+
const FETCH_ENHANCERS = 'f';
|
|
61
61
|
const FETCH_RSC_INPUT_TRANSFORMERS = 't';
|
|
62
62
|
const CALL_SERVER_ELEMENTS_LISTENERS = 'l';
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
|
|
63
|
+
const fetchRscStore = {};
|
|
64
|
+
const getFetchFn = ()=>{
|
|
65
|
+
let fetchFn = fetch;
|
|
66
|
+
const enhancers = fetchRscStore[FETCH_ENHANCERS];
|
|
67
|
+
if (enhancers) {
|
|
68
|
+
for (const enhance of enhancers){
|
|
69
|
+
fetchFn = enhance(fetchFn);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return fetchFn;
|
|
73
|
+
};
|
|
74
|
+
const getSetElements = ()=>{
|
|
75
|
+
const setElements = fetchRscStore[SET_ELEMENTS];
|
|
76
|
+
if (!setElements) {
|
|
77
|
+
throw new Error('Missing Root component');
|
|
78
|
+
}
|
|
79
|
+
return setElements;
|
|
80
|
+
};
|
|
81
|
+
const requestRsc = (fetchFn, rscPath, rscParams, temporaryReferences, signal)=>{
|
|
66
82
|
const url = BASE_RSC_PATH + encodeRscPath(rscPath);
|
|
83
|
+
const init = {};
|
|
84
|
+
if (signal) {
|
|
85
|
+
init.signal = signal;
|
|
86
|
+
}
|
|
67
87
|
if (rscParams === undefined) {
|
|
68
|
-
return fetchFn(url);
|
|
88
|
+
return fetchFn(url, init);
|
|
69
89
|
}
|
|
70
90
|
if (rscParams instanceof URLSearchParams) {
|
|
71
|
-
return fetchFn(url + '?' + rscParams);
|
|
91
|
+
return fetchFn(url + '?' + rscParams, init);
|
|
72
92
|
}
|
|
73
93
|
return encodeReply(rscParams, {
|
|
74
94
|
temporaryReferences
|
|
75
95
|
}).then((body)=>fetchFn(url, {
|
|
96
|
+
...init,
|
|
76
97
|
method: 'POST',
|
|
77
98
|
body
|
|
78
99
|
}));
|
|
79
100
|
};
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const decodeRsc = (getStore, responsePromise, temporaryReferences, debugChannel)=>createFromFetch(checkStatus(responsePromise), {
|
|
83
|
-
callServer: (funcId, args)=>unstable_callServerRsc(funcId, args, getStore),
|
|
101
|
+
const decodeRsc = (responsePromise, temporaryReferences, debugChannel)=>createFromFetch(checkStatus(responsePromise), {
|
|
102
|
+
callServer: (funcId, args)=>unstable_callServerRsc(funcId, args),
|
|
84
103
|
debugChannel,
|
|
85
104
|
temporaryReferences
|
|
86
105
|
});
|
|
87
|
-
const reloadOnBuildIdMismatch = (
|
|
106
|
+
const reloadOnBuildIdMismatch = (elements, onBuildIdMismatch)=>{
|
|
88
107
|
if (!import.meta.env?.WAKU_BUILD_ID) {
|
|
89
108
|
return;
|
|
90
109
|
}
|
|
91
110
|
Promise.resolve(elements).then((data)=>{
|
|
92
111
|
if (data._buildId !== import.meta.env.WAKU_BUILD_ID) {
|
|
93
|
-
(
|
|
112
|
+
(onBuildIdMismatch ?? (()=>window.location.reload()))();
|
|
94
113
|
}
|
|
95
114
|
}, ()=>{});
|
|
96
115
|
};
|
|
97
|
-
const prefetchRscInternal = (
|
|
98
|
-
const fetchFn = fetchRscStore[FETCH_FN] || fetch;
|
|
116
|
+
const prefetchRscInternal = (rscPath, rscParams)=>{
|
|
99
117
|
const temporaryReferences = createTemporaryReferenceSet();
|
|
100
|
-
const responsePromise = requestRsc(
|
|
101
|
-
addPrefetchEntry(rscPath, rscParams,
|
|
118
|
+
const responsePromise = requestRsc(getFetchFn(), rscPath, rscParams, temporaryReferences, undefined);
|
|
119
|
+
addPrefetchEntry(rscPath, rscParams, decodeRsc(responsePromise, temporaryReferences, undefined));
|
|
102
120
|
};
|
|
103
|
-
const fetchRscElements = (
|
|
104
|
-
const prefetched = consumePrefetchEntry(rscPath, rscParams
|
|
121
|
+
const fetchRscElements = (rscPath, rscParams, options)=>{
|
|
122
|
+
const prefetched = consumePrefetchEntry(rscPath, rscParams);
|
|
105
123
|
if (prefetched) {
|
|
106
|
-
reloadOnBuildIdMismatch(
|
|
124
|
+
reloadOnBuildIdMismatch(prefetched, options?.onBuildIdMismatch);
|
|
107
125
|
return prefetched;
|
|
108
126
|
}
|
|
109
127
|
const initial = consumeInitialRscEntry();
|
|
110
|
-
const baseFetchFn =
|
|
128
|
+
const baseFetchFn = getFetchFn();
|
|
111
129
|
const debug = import.meta.hot ? setupDebugChannel(baseFetchFn, !!initial, initial?.debugId) : undefined;
|
|
112
130
|
const fetchFn = debug?.fetchFn || baseFetchFn;
|
|
113
131
|
const temporaryReferences = createTemporaryReferenceSet();
|
|
114
|
-
const responsePromise = initial ? initial.response : requestRsc(fetchFn, rscPath, rscParams, temporaryReferences);
|
|
115
|
-
const elements = decodeRsc(
|
|
116
|
-
reloadOnBuildIdMismatch(
|
|
132
|
+
const responsePromise = initial ? initial.response : requestRsc(fetchFn, rscPath, rscParams, temporaryReferences, options?.signal);
|
|
133
|
+
const elements = decodeRsc(responsePromise, temporaryReferences, debug?.debugChannel);
|
|
134
|
+
reloadOnBuildIdMismatch(elements, options?.onBuildIdMismatch);
|
|
117
135
|
if (initial) {
|
|
118
136
|
const { close } = initial;
|
|
119
137
|
waitForRootPrerequisites(elements).then(close, close);
|
|
120
138
|
}
|
|
121
139
|
return elements;
|
|
122
140
|
};
|
|
123
|
-
const applyInputTransformers = (
|
|
141
|
+
const applyInputTransformers = (rscPath, rscParams, prefetchOnly)=>{
|
|
124
142
|
const fetchRscInputTransformers = fetchRscStore[FETCH_RSC_INPUT_TRANSFORMERS];
|
|
125
143
|
if (fetchRscInputTransformers) {
|
|
126
144
|
for (const transformFetchRscInput of fetchRscInputTransformers){
|
|
@@ -133,27 +151,26 @@ const applyInputTransformers = (fetchRscStore, rscPath, rscParams, prefetchOnly)
|
|
|
133
151
|
prefetchOnly
|
|
134
152
|
];
|
|
135
153
|
};
|
|
136
|
-
const fetchRscInternal = (
|
|
137
|
-
[rscPath, rscParams, prefetchOnly] = applyInputTransformers(
|
|
154
|
+
const fetchRscInternal = (rscPath, rscParams, prefetchOnly, options)=>{
|
|
155
|
+
[rscPath, rscParams, prefetchOnly] = applyInputTransformers(rscPath, rscParams, prefetchOnly);
|
|
138
156
|
if (prefetchOnly) {
|
|
139
157
|
if (!hasPrefetchEntry(rscPath, rscParams)) {
|
|
140
|
-
prefetchRscInternal(
|
|
158
|
+
prefetchRscInternal(rscPath, rscParams);
|
|
141
159
|
}
|
|
142
160
|
return undefined;
|
|
143
161
|
}
|
|
144
|
-
return fetchRscElements(
|
|
162
|
+
return fetchRscElements(rscPath, rscParams, options);
|
|
145
163
|
};
|
|
146
164
|
/**
|
|
147
165
|
* callServer callback
|
|
148
166
|
* This is not a public API.
|
|
149
|
-
*/ export const unstable_callServerRsc = async (funcId, args
|
|
150
|
-
const fetchRscStore = unstable_enhanceFetchRscStore(defaultFetchRscStore);
|
|
151
|
-
const setElements = fetchRscStore[SET_ELEMENTS];
|
|
152
|
-
const callServerElementsListeners = fetchRscStore[CALL_SERVER_ELEMENTS_LISTENERS];
|
|
167
|
+
*/ export const unstable_callServerRsc = async (funcId, args)=>{
|
|
153
168
|
const rscPath = encodeFuncId(funcId);
|
|
154
169
|
const rscParams = args.length === 1 && args[0] instanceof URLSearchParams ? args[0] : args;
|
|
155
|
-
const { _value: value, ...data } = await fetchRscInternal(
|
|
170
|
+
const { _value: value, ...data } = await fetchRscInternal(rscPath, rscParams, false, undefined);
|
|
156
171
|
if (Object.keys(data).length) {
|
|
172
|
+
const setElements = getSetElements();
|
|
173
|
+
const callServerElementsListeners = fetchRscStore[CALL_SERVER_ELEMENTS_LISTENERS];
|
|
157
174
|
startTransition(()=>{
|
|
158
175
|
callServerElementsListeners?.forEach((listener)=>{
|
|
159
176
|
listener(data);
|
|
@@ -163,42 +180,68 @@ const fetchRscInternal = (fetchRscStore, rscPath, rscParams, prefetchOnly)=>{
|
|
|
163
180
|
}
|
|
164
181
|
return value;
|
|
165
182
|
};
|
|
166
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Register a listener that runs when a server action returns new elements.
|
|
185
|
+
* Returns a function that unregisters the listener.
|
|
186
|
+
*/ export const unstable_registerCallServerElementsListener = (listener)=>{
|
|
167
187
|
const callServerElementsListeners = fetchRscStore[CALL_SERVER_ELEMENTS_LISTENERS] ||= new Set();
|
|
168
188
|
callServerElementsListeners.add(listener);
|
|
169
189
|
return ()=>{
|
|
170
190
|
callServerElementsListeners.delete(listener);
|
|
171
191
|
};
|
|
172
192
|
};
|
|
173
|
-
|
|
174
|
-
|
|
193
|
+
/**
|
|
194
|
+
* Register a fetch enhancer applied to every RSC request (e.g. to add headers).
|
|
195
|
+
* Enhancers are composed in registration order. Returns a function that
|
|
196
|
+
* unregisters the enhancer.
|
|
197
|
+
*/ export const unstable_registerFetchEnhancer = (enhance)=>{
|
|
198
|
+
const fetchEnhancers = fetchRscStore[FETCH_ENHANCERS] ||= new Set();
|
|
199
|
+
fetchEnhancers.add(enhance);
|
|
200
|
+
return ()=>{
|
|
201
|
+
fetchEnhancers.delete(enhance);
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
let registerTransformerStoreArgWarned = false;
|
|
205
|
+
export function unstable_registerFetchRscInputTransformer(storeOrTransform, maybeTransform) {
|
|
206
|
+
let transformFetchRscInput;
|
|
207
|
+
if (typeof storeOrTransform === 'function') {
|
|
208
|
+
transformFetchRscInput = storeOrTransform;
|
|
209
|
+
} else {
|
|
210
|
+
transformFetchRscInput = maybeTransform;
|
|
211
|
+
if (!registerTransformerStoreArgWarned) {
|
|
212
|
+
registerTransformerStoreArgWarned = true;
|
|
213
|
+
console.warn('[waku] Passing a store to `unstable_registerFetchRscInputTransformer` is deprecated. Pass only the transformer.');
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const fetchRscInputTransformers = fetchRscStore[FETCH_RSC_INPUT_TRANSFORMERS] ||= new Set();
|
|
175
217
|
fetchRscInputTransformers.add(transformFetchRscInput);
|
|
176
218
|
return ()=>{
|
|
177
219
|
fetchRscInputTransformers.delete(transformFetchRscInput);
|
|
178
220
|
};
|
|
221
|
+
}
|
|
222
|
+
const registerHmrRefetch = (refetch)=>{
|
|
223
|
+
globalThis.__WAKU_RSC_RELOAD_LISTENERS__ ||= [];
|
|
224
|
+
const index = globalThis.__WAKU_RSC_RELOAD_LISTENERS__.indexOf(globalThis.__WAKU_REFETCH_RSC__);
|
|
225
|
+
if (index !== -1) {
|
|
226
|
+
globalThis.__WAKU_RSC_RELOAD_LISTENERS__.splice(index, 1, refetch);
|
|
227
|
+
} else {
|
|
228
|
+
globalThis.__WAKU_RSC_RELOAD_LISTENERS__.push(refetch);
|
|
229
|
+
}
|
|
230
|
+
globalThis.__WAKU_REFETCH_RSC__ = refetch;
|
|
179
231
|
};
|
|
180
|
-
export const unstable_fetchRsc = (rscPath, rscParams,
|
|
181
|
-
const fetchRscStore = unstable_enhanceFetchRscStore(defaultFetchRscStore);
|
|
232
|
+
/** Fetch elements for an RSC path, reusing a cached or prefetched result. */ export const unstable_fetchRsc = (rscPath, rscParams, options)=>{
|
|
182
233
|
if (import.meta.hot) {
|
|
183
|
-
|
|
234
|
+
registerHmrRefetch(()=>{
|
|
184
235
|
delete fetchRscStore[ENTRY];
|
|
185
|
-
const data = unstable_fetchRsc(rscPath, rscParams,
|
|
186
|
-
|
|
187
|
-
};
|
|
188
|
-
globalThis.__WAKU_RSC_RELOAD_LISTENERS__ ||= [];
|
|
189
|
-
const index = globalThis.__WAKU_RSC_RELOAD_LISTENERS__.indexOf(globalThis.__WAKU_REFETCH_RSC__);
|
|
190
|
-
if (index !== -1) {
|
|
191
|
-
globalThis.__WAKU_RSC_RELOAD_LISTENERS__.splice(index, 1, refetchRsc);
|
|
192
|
-
} else {
|
|
193
|
-
globalThis.__WAKU_RSC_RELOAD_LISTENERS__.push(refetchRsc);
|
|
194
|
-
}
|
|
195
|
-
globalThis.__WAKU_REFETCH_RSC__ = refetchRsc;
|
|
236
|
+
const data = unstable_fetchRsc(rscPath, rscParams, options);
|
|
237
|
+
getSetElements()(()=>data);
|
|
238
|
+
});
|
|
196
239
|
}
|
|
197
240
|
const entry = fetchRscStore[ENTRY];
|
|
198
241
|
if (entry && entry[0] === rscPath && entry[1] === rscParams) {
|
|
199
242
|
return entry[2];
|
|
200
243
|
}
|
|
201
|
-
const data = fetchRscInternal(
|
|
244
|
+
const data = fetchRscInternal(rscPath, rscParams, false, options);
|
|
202
245
|
fetchRscStore[ENTRY] = [
|
|
203
246
|
rscPath,
|
|
204
247
|
rscParams,
|
|
@@ -206,60 +249,36 @@ export const unstable_fetchRsc = (rscPath, rscParams, unstable_enhanceFetchRscSt
|
|
|
206
249
|
];
|
|
207
250
|
return data;
|
|
208
251
|
};
|
|
209
|
-
export const unstable_prefetchRsc = (rscPath, rscParams
|
|
210
|
-
|
|
211
|
-
fetchRscInternal(fetchRscStore, rscPath, rscParams, true);
|
|
252
|
+
/** Eagerly fetch and cache elements so a later fetch reuses them. */ export const unstable_prefetchRsc = (rscPath, rscParams)=>{
|
|
253
|
+
fetchRscInternal(rscPath, rscParams, true, undefined);
|
|
212
254
|
};
|
|
213
|
-
export const unstable_withEnhanceFetchFn = (enhanceFetchFn)=>(fetchRscStore)=>({
|
|
214
|
-
...fetchRscStore,
|
|
215
|
-
[FETCH_FN]: enhanceFetchFn(fetchRscStore[FETCH_FN] || fetch)
|
|
216
|
-
});
|
|
217
|
-
export const unstable_withBuildIdMismatchHandler = (handler)=>(fetchRscStore)=>({
|
|
218
|
-
...fetchRscStore,
|
|
219
|
-
[ON_BUILD_ID_MISMATCH]: handler
|
|
220
|
-
});
|
|
221
255
|
const RefetchContext = /*#__PURE__*/ createContext(()=>{
|
|
222
256
|
throw new Error('Missing Root component');
|
|
223
257
|
});
|
|
224
258
|
const ElementsContext = /*#__PURE__*/ createContext(null);
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
return fetchRscStore;
|
|
232
|
-
};
|
|
233
|
-
export const Root = ({ initialRscPath, initialRscParams, unstable_fetchRscStore = defaultFetchRscStore, children })=>{
|
|
234
|
-
const [elements, setElements] = useState(()=>unstable_fetchRsc(initialRscPath || '', initialRscParams, ()=>unstable_fetchRscStore));
|
|
259
|
+
/**
|
|
260
|
+
* Client root. Seeds the initial elements, bridges the store to React state,
|
|
261
|
+
* and provides the elements to `Slot` descendants.
|
|
262
|
+
*/ export const Root = ({ initialRscPath, initialRscParams, children })=>{
|
|
263
|
+
const [elements, setElements] = useState(()=>unstable_fetchRsc(initialRscPath || '', initialRscParams));
|
|
235
264
|
useEffect(()=>{
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const refetch = useCallback(async (rscPath, rscParams, unstable_enhanceFetchRscStore = (s)=>s)=>{
|
|
242
|
-
// clear cache entry before fetching
|
|
243
|
-
// eslint-disable-next-line react-hooks/immutability
|
|
244
|
-
delete unstable_fetchRscStore[ENTRY]; // use non-enhanced store
|
|
245
|
-
const data = unstable_fetchRsc(rscPath, rscParams, ()=>unstable_enhanceFetchRscStore(unstable_fetchRscStore));
|
|
265
|
+
fetchRscStore[SET_ELEMENTS] = setElements;
|
|
266
|
+
}, []);
|
|
267
|
+
const refetch = useCallback(async (rscPath, rscParams, options)=>{
|
|
268
|
+
delete fetchRscStore[ENTRY];
|
|
269
|
+
const data = unstable_fetchRsc(rscPath, rscParams, options);
|
|
246
270
|
const dataWithoutErrors = Promise.resolve(data).catch(()=>({}));
|
|
247
271
|
setElements((prev)=>mergeElementsPromise(prev, dataWithoutErrors));
|
|
248
272
|
return data;
|
|
249
|
-
}, [
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
children: [
|
|
259
|
-
DEFAULT_HTML_HEAD,
|
|
260
|
-
children
|
|
261
|
-
]
|
|
262
|
-
})
|
|
273
|
+
}, []);
|
|
274
|
+
return /*#__PURE__*/ _jsx(RefetchContext, {
|
|
275
|
+
value: refetch,
|
|
276
|
+
children: /*#__PURE__*/ _jsxs(ElementsContext, {
|
|
277
|
+
value: elements,
|
|
278
|
+
children: [
|
|
279
|
+
DEFAULT_HTML_HEAD,
|
|
280
|
+
children
|
|
281
|
+
]
|
|
263
282
|
})
|
|
264
283
|
});
|
|
265
284
|
};
|
|
@@ -274,6 +293,18 @@ export const useElementsPromise_UNSTABLE = ()=>{
|
|
|
274
293
|
}
|
|
275
294
|
return elementsPromise;
|
|
276
295
|
};
|
|
296
|
+
let useFetchRscStoreDeprecationWarned = false;
|
|
297
|
+
/**
|
|
298
|
+
* @deprecated The store is an internal singleton; you no longer need to pass it
|
|
299
|
+
* to `unstable_registerFetchRscInputTransformer`. This will be removed in a
|
|
300
|
+
* future release.
|
|
301
|
+
*/ export const useFetchRscStore_UNSTABLE = ()=>{
|
|
302
|
+
if (!useFetchRscStoreDeprecationWarned) {
|
|
303
|
+
useFetchRscStoreDeprecationWarned = true;
|
|
304
|
+
console.warn('[waku] `useFetchRscStore_UNSTABLE` is deprecated and will be removed.');
|
|
305
|
+
}
|
|
306
|
+
return fetchRscStore;
|
|
307
|
+
};
|
|
277
308
|
/**
|
|
278
309
|
* Slot component
|
|
279
310
|
* This is used under the Root component.
|
|
@@ -306,17 +337,14 @@ export const useElementsPromise_UNSTABLE = ()=>{
|
|
|
306
337
|
/**
|
|
307
338
|
* ServerRoot for SSR
|
|
308
339
|
* This is not a public API.
|
|
309
|
-
*/ export const INTERNAL_ServerRoot = ({ elementsPromise, children })=>/*#__PURE__*/ _jsx(
|
|
310
|
-
value: {},
|
|
311
|
-
children: /*#__PURE__*/
|
|
312
|
-
value:
|
|
313
|
-
children:
|
|
314
|
-
|
|
315
|
-
children
|
|
316
|
-
|
|
317
|
-
children
|
|
318
|
-
]
|
|
319
|
-
})
|
|
340
|
+
*/ export const INTERNAL_ServerRoot = ({ elementsPromise, children })=>/*#__PURE__*/ _jsx(RefetchContext, {
|
|
341
|
+
value: async ()=>({}),
|
|
342
|
+
children: /*#__PURE__*/ _jsxs(ElementsContext, {
|
|
343
|
+
value: elementsPromise,
|
|
344
|
+
children: [
|
|
345
|
+
DEFAULT_HTML_HEAD,
|
|
346
|
+
children
|
|
347
|
+
]
|
|
320
348
|
})
|
|
321
349
|
});
|
|
322
350
|
|