@effector-tanstack-query/core 0.1.1 → 0.2.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/dist/index.cjs +5 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/prefetchQueries.cjs +14 -0
- package/dist/prefetchQueries.cjs.map +1 -0
- package/dist/prefetchQueries.d.cts +59 -0
- package/dist/prefetchQueries.d.ts +59 -0
- package/dist/prefetchQueries.js +12 -0
- package/dist/prefetchQueries.js.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +5 -0
- package/src/prefetchQueries.ts +67 -0
package/dist/index.cjs
CHANGED
|
@@ -5,6 +5,7 @@ var createInfiniteQuery_cjs = require('./createInfiniteQuery.cjs');
|
|
|
5
5
|
var createMutation_cjs = require('./createMutation.cjs');
|
|
6
6
|
var createInvalidate_cjs = require('./createInvalidate.cjs');
|
|
7
7
|
var queryClient_cjs = require('./queryClient.cjs');
|
|
8
|
+
var prefetchQueries_cjs = require('./prefetchQueries.cjs');
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
|
|
@@ -32,5 +33,9 @@ Object.defineProperty(exports, "setQueryClient", {
|
|
|
32
33
|
enumerable: true,
|
|
33
34
|
get: function () { return queryClient_cjs.setQueryClient; }
|
|
34
35
|
});
|
|
36
|
+
Object.defineProperty(exports, "prefetchQueries", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function () { return prefetchQueries_cjs.prefetchQueries; }
|
|
39
|
+
});
|
|
35
40
|
//# sourceMappingURL=index.cjs.map
|
|
36
41
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.cts
CHANGED
|
@@ -3,6 +3,7 @@ export { createInfiniteQuery } from './createInfiniteQuery.cjs';
|
|
|
3
3
|
export { createMutation } from './createMutation.cjs';
|
|
4
4
|
export { CreateInvalidateOptions, createInvalidate } from './createInvalidate.cjs';
|
|
5
5
|
export { $queryClient, setQueryClient } from './queryClient.cjs';
|
|
6
|
+
export { PrefetchQueriesConfig, PrefetchableQuery, prefetchQueries } from './prefetchQueries.cjs';
|
|
6
7
|
export { CreateInfiniteQueryOptions, CreateMutationOptions, CreateQueryOptions, EffectorQueryKey, InfiniteQueryResult, MutationResult, MutationStatus, QueryResult, StoreOrValue } from './types.cjs';
|
|
7
8
|
import '@tanstack/query-core';
|
|
8
9
|
import 'effector';
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { createInfiniteQuery } from './createInfiniteQuery.js';
|
|
|
3
3
|
export { createMutation } from './createMutation.js';
|
|
4
4
|
export { CreateInvalidateOptions, createInvalidate } from './createInvalidate.js';
|
|
5
5
|
export { $queryClient, setQueryClient } from './queryClient.js';
|
|
6
|
+
export { PrefetchQueriesConfig, PrefetchableQuery, prefetchQueries } from './prefetchQueries.js';
|
|
6
7
|
export { CreateInfiniteQueryOptions, CreateMutationOptions, CreateQueryOptions, EffectorQueryKey, InfiniteQueryResult, MutationResult, MutationStatus, QueryResult, StoreOrValue } from './types.js';
|
|
7
8
|
import '@tanstack/query-core';
|
|
8
9
|
import 'effector';
|
package/dist/index.js
CHANGED
|
@@ -3,5 +3,6 @@ export { createInfiniteQuery } from './createInfiniteQuery.js';
|
|
|
3
3
|
export { createMutation } from './createMutation.js';
|
|
4
4
|
export { createInvalidate } from './createInvalidate.js';
|
|
5
5
|
export { $queryClient, setQueryClient } from './queryClient.js';
|
|
6
|
+
export { prefetchQueries } from './prefetchQueries.js';
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
|
7
8
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var effector = require('effector');
|
|
4
|
+
|
|
5
|
+
// src/prefetchQueries.ts
|
|
6
|
+
async function prefetchQueries(queries, config) {
|
|
7
|
+
const { scope } = config;
|
|
8
|
+
await Promise.all(queries.map((q) => effector.allSettled(q.prefetch, { scope })));
|
|
9
|
+
await Promise.all(queries.map((q) => effector.allSettled(q.mounted, { scope })));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
exports.prefetchQueries = prefetchQueries;
|
|
13
|
+
//# sourceMappingURL=prefetchQueries.cjs.map
|
|
14
|
+
//# sourceMappingURL=prefetchQueries.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/prefetchQueries.ts"],"names":["allSettled"],"mappings":";;;;;AA2DA,eAAsB,eAAA,CACpB,SACA,MAAA,EACe;AACf,EAAA,MAAM,EAAE,OAAM,GAAI,MAAA;AAClB,EAAA,MAAM,OAAA,CAAQ,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAMA,mBAAA,CAAW,CAAA,CAAE,QAAA,EAAU,EAAE,KAAA,EAAO,CAAC,CAAC,CAAA;AACvE,EAAA,MAAM,OAAA,CAAQ,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAMA,mBAAA,CAAW,CAAA,CAAE,OAAA,EAAS,EAAE,KAAA,EAAO,CAAC,CAAC,CAAA;AACxE","file":"prefetchQueries.cjs","sourcesContent":["import { allSettled } from 'effector'\nimport type { EventCallable, Scope } from 'effector'\n\n/**\n * Structural shape of any factory result that exposes the two SSR\n * lifecycle events. Both `QueryResult` and `InfiniteQueryResult` satisfy\n * this without forcing the caller to widen their `TData` / `TError` type\n * parameters.\n */\nexport interface PrefetchableQuery {\n prefetch: EventCallable<void>\n mounted: EventCallable<void>\n}\n\nexport interface PrefetchQueriesConfig {\n /** Scope to run the lifecycle events in. Required — `allSettled` cannot\n * await unit triggers outside of a scope. */\n scope: Scope\n}\n\n/**\n * Server-side helper that fills **both** SSR layers for a set of queries:\n *\n * 1. `await allSettled(q.prefetch, { scope })` for each query — awaits\n * `queryClient.fetchQuery(...)` so by the time the promise resolves\n * the cache holds the data.\n * 2. `await allSettled(q.mounted, { scope })` for each query — creates\n * the per-scope observer; its synchronous `getCurrentResult()`\n * dispatch reads from the now-populated cache and writes into the\n * effector stores (`$data`, `$status`, …). This is what makes\n * `serialize(scope)` ship populated stores, which in turn lets the\n * server-rendered HTML show data on first paint.\n *\n * Skipping step 2 (calling only `prefetch`) leaves the effector stores at\n * their defaults — `serialize(scope)` returns nothing useful, the\n * server-rendered HTML shows loading, and the user sees a flash on\n * hydration. This helper exists so that bug is impossible to write.\n *\n * Both phases run in parallel within themselves (`Promise.all`) but\n * sequentially across phases (`mounted` must see a populated cache).\n *\n * Snapshot the layers yourself afterwards — `dehydrate(queryClient)` for\n * the cache and `serialize(scope)` for the stores — and ship both to the\n * client (e.g. via `<HydrationBoundary state={...}>` + `<EffectorNext\n * values={...}>` or `fork({ values: ... })`).\n *\n * @example\n * ```ts\n * const queryClient = new QueryClient()\n * const scope = fork({ values: [[$queryClient, queryClient]] })\n *\n * await prefetchQueries([listQuery, pokemonQuery], { scope })\n *\n * return {\n * dehydratedQueryClient: dehydrate(queryClient),\n * serializedScope: serialize(scope),\n * }\n * ```\n */\nexport async function prefetchQueries(\n queries: ReadonlyArray<PrefetchableQuery>,\n config: PrefetchQueriesConfig,\n): Promise<void> {\n const { scope } = config\n await Promise.all(queries.map((q) => allSettled(q.prefetch, { scope })))\n await Promise.all(queries.map((q) => allSettled(q.mounted, { scope })))\n}\n"]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Scope, EventCallable } from 'effector';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Structural shape of any factory result that exposes the two SSR
|
|
5
|
+
* lifecycle events. Both `QueryResult` and `InfiniteQueryResult` satisfy
|
|
6
|
+
* this without forcing the caller to widen their `TData` / `TError` type
|
|
7
|
+
* parameters.
|
|
8
|
+
*/
|
|
9
|
+
interface PrefetchableQuery {
|
|
10
|
+
prefetch: EventCallable<void>;
|
|
11
|
+
mounted: EventCallable<void>;
|
|
12
|
+
}
|
|
13
|
+
interface PrefetchQueriesConfig {
|
|
14
|
+
/** Scope to run the lifecycle events in. Required — `allSettled` cannot
|
|
15
|
+
* await unit triggers outside of a scope. */
|
|
16
|
+
scope: Scope;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Server-side helper that fills **both** SSR layers for a set of queries:
|
|
20
|
+
*
|
|
21
|
+
* 1. `await allSettled(q.prefetch, { scope })` for each query — awaits
|
|
22
|
+
* `queryClient.fetchQuery(...)` so by the time the promise resolves
|
|
23
|
+
* the cache holds the data.
|
|
24
|
+
* 2. `await allSettled(q.mounted, { scope })` for each query — creates
|
|
25
|
+
* the per-scope observer; its synchronous `getCurrentResult()`
|
|
26
|
+
* dispatch reads from the now-populated cache and writes into the
|
|
27
|
+
* effector stores (`$data`, `$status`, …). This is what makes
|
|
28
|
+
* `serialize(scope)` ship populated stores, which in turn lets the
|
|
29
|
+
* server-rendered HTML show data on first paint.
|
|
30
|
+
*
|
|
31
|
+
* Skipping step 2 (calling only `prefetch`) leaves the effector stores at
|
|
32
|
+
* their defaults — `serialize(scope)` returns nothing useful, the
|
|
33
|
+
* server-rendered HTML shows loading, and the user sees a flash on
|
|
34
|
+
* hydration. This helper exists so that bug is impossible to write.
|
|
35
|
+
*
|
|
36
|
+
* Both phases run in parallel within themselves (`Promise.all`) but
|
|
37
|
+
* sequentially across phases (`mounted` must see a populated cache).
|
|
38
|
+
*
|
|
39
|
+
* Snapshot the layers yourself afterwards — `dehydrate(queryClient)` for
|
|
40
|
+
* the cache and `serialize(scope)` for the stores — and ship both to the
|
|
41
|
+
* client (e.g. via `<HydrationBoundary state={...}>` + `<EffectorNext
|
|
42
|
+
* values={...}>` or `fork({ values: ... })`).
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* const queryClient = new QueryClient()
|
|
47
|
+
* const scope = fork({ values: [[$queryClient, queryClient]] })
|
|
48
|
+
*
|
|
49
|
+
* await prefetchQueries([listQuery, pokemonQuery], { scope })
|
|
50
|
+
*
|
|
51
|
+
* return {
|
|
52
|
+
* dehydratedQueryClient: dehydrate(queryClient),
|
|
53
|
+
* serializedScope: serialize(scope),
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
declare function prefetchQueries(queries: ReadonlyArray<PrefetchableQuery>, config: PrefetchQueriesConfig): Promise<void>;
|
|
58
|
+
|
|
59
|
+
export { type PrefetchQueriesConfig, type PrefetchableQuery, prefetchQueries };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Scope, EventCallable } from 'effector';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Structural shape of any factory result that exposes the two SSR
|
|
5
|
+
* lifecycle events. Both `QueryResult` and `InfiniteQueryResult` satisfy
|
|
6
|
+
* this without forcing the caller to widen their `TData` / `TError` type
|
|
7
|
+
* parameters.
|
|
8
|
+
*/
|
|
9
|
+
interface PrefetchableQuery {
|
|
10
|
+
prefetch: EventCallable<void>;
|
|
11
|
+
mounted: EventCallable<void>;
|
|
12
|
+
}
|
|
13
|
+
interface PrefetchQueriesConfig {
|
|
14
|
+
/** Scope to run the lifecycle events in. Required — `allSettled` cannot
|
|
15
|
+
* await unit triggers outside of a scope. */
|
|
16
|
+
scope: Scope;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Server-side helper that fills **both** SSR layers for a set of queries:
|
|
20
|
+
*
|
|
21
|
+
* 1. `await allSettled(q.prefetch, { scope })` for each query — awaits
|
|
22
|
+
* `queryClient.fetchQuery(...)` so by the time the promise resolves
|
|
23
|
+
* the cache holds the data.
|
|
24
|
+
* 2. `await allSettled(q.mounted, { scope })` for each query — creates
|
|
25
|
+
* the per-scope observer; its synchronous `getCurrentResult()`
|
|
26
|
+
* dispatch reads from the now-populated cache and writes into the
|
|
27
|
+
* effector stores (`$data`, `$status`, …). This is what makes
|
|
28
|
+
* `serialize(scope)` ship populated stores, which in turn lets the
|
|
29
|
+
* server-rendered HTML show data on first paint.
|
|
30
|
+
*
|
|
31
|
+
* Skipping step 2 (calling only `prefetch`) leaves the effector stores at
|
|
32
|
+
* their defaults — `serialize(scope)` returns nothing useful, the
|
|
33
|
+
* server-rendered HTML shows loading, and the user sees a flash on
|
|
34
|
+
* hydration. This helper exists so that bug is impossible to write.
|
|
35
|
+
*
|
|
36
|
+
* Both phases run in parallel within themselves (`Promise.all`) but
|
|
37
|
+
* sequentially across phases (`mounted` must see a populated cache).
|
|
38
|
+
*
|
|
39
|
+
* Snapshot the layers yourself afterwards — `dehydrate(queryClient)` for
|
|
40
|
+
* the cache and `serialize(scope)` for the stores — and ship both to the
|
|
41
|
+
* client (e.g. via `<HydrationBoundary state={...}>` + `<EffectorNext
|
|
42
|
+
* values={...}>` or `fork({ values: ... })`).
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* const queryClient = new QueryClient()
|
|
47
|
+
* const scope = fork({ values: [[$queryClient, queryClient]] })
|
|
48
|
+
*
|
|
49
|
+
* await prefetchQueries([listQuery, pokemonQuery], { scope })
|
|
50
|
+
*
|
|
51
|
+
* return {
|
|
52
|
+
* dehydratedQueryClient: dehydrate(queryClient),
|
|
53
|
+
* serializedScope: serialize(scope),
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
declare function prefetchQueries(queries: ReadonlyArray<PrefetchableQuery>, config: PrefetchQueriesConfig): Promise<void>;
|
|
58
|
+
|
|
59
|
+
export { type PrefetchQueriesConfig, type PrefetchableQuery, prefetchQueries };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { allSettled } from 'effector';
|
|
2
|
+
|
|
3
|
+
// src/prefetchQueries.ts
|
|
4
|
+
async function prefetchQueries(queries, config) {
|
|
5
|
+
const { scope } = config;
|
|
6
|
+
await Promise.all(queries.map((q) => allSettled(q.prefetch, { scope })));
|
|
7
|
+
await Promise.all(queries.map((q) => allSettled(q.mounted, { scope })));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { prefetchQueries };
|
|
11
|
+
//# sourceMappingURL=prefetchQueries.js.map
|
|
12
|
+
//# sourceMappingURL=prefetchQueries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/prefetchQueries.ts"],"names":[],"mappings":";;;AA2DA,eAAsB,eAAA,CACpB,SACA,MAAA,EACe;AACf,EAAA,MAAM,EAAE,OAAM,GAAI,MAAA;AAClB,EAAA,MAAM,OAAA,CAAQ,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,UAAA,CAAW,CAAA,CAAE,QAAA,EAAU,EAAE,KAAA,EAAO,CAAC,CAAC,CAAA;AACvE,EAAA,MAAM,OAAA,CAAQ,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,UAAA,CAAW,CAAA,CAAE,OAAA,EAAS,EAAE,KAAA,EAAO,CAAC,CAAC,CAAA;AACxE","file":"prefetchQueries.js","sourcesContent":["import { allSettled } from 'effector'\nimport type { EventCallable, Scope } from 'effector'\n\n/**\n * Structural shape of any factory result that exposes the two SSR\n * lifecycle events. Both `QueryResult` and `InfiniteQueryResult` satisfy\n * this without forcing the caller to widen their `TData` / `TError` type\n * parameters.\n */\nexport interface PrefetchableQuery {\n prefetch: EventCallable<void>\n mounted: EventCallable<void>\n}\n\nexport interface PrefetchQueriesConfig {\n /** Scope to run the lifecycle events in. Required — `allSettled` cannot\n * await unit triggers outside of a scope. */\n scope: Scope\n}\n\n/**\n * Server-side helper that fills **both** SSR layers for a set of queries:\n *\n * 1. `await allSettled(q.prefetch, { scope })` for each query — awaits\n * `queryClient.fetchQuery(...)` so by the time the promise resolves\n * the cache holds the data.\n * 2. `await allSettled(q.mounted, { scope })` for each query — creates\n * the per-scope observer; its synchronous `getCurrentResult()`\n * dispatch reads from the now-populated cache and writes into the\n * effector stores (`$data`, `$status`, …). This is what makes\n * `serialize(scope)` ship populated stores, which in turn lets the\n * server-rendered HTML show data on first paint.\n *\n * Skipping step 2 (calling only `prefetch`) leaves the effector stores at\n * their defaults — `serialize(scope)` returns nothing useful, the\n * server-rendered HTML shows loading, and the user sees a flash on\n * hydration. This helper exists so that bug is impossible to write.\n *\n * Both phases run in parallel within themselves (`Promise.all`) but\n * sequentially across phases (`mounted` must see a populated cache).\n *\n * Snapshot the layers yourself afterwards — `dehydrate(queryClient)` for\n * the cache and `serialize(scope)` for the stores — and ship both to the\n * client (e.g. via `<HydrationBoundary state={...}>` + `<EffectorNext\n * values={...}>` or `fork({ values: ... })`).\n *\n * @example\n * ```ts\n * const queryClient = new QueryClient()\n * const scope = fork({ values: [[$queryClient, queryClient]] })\n *\n * await prefetchQueries([listQuery, pokemonQuery], { scope })\n *\n * return {\n * dehydratedQueryClient: dehydrate(queryClient),\n * serializedScope: serialize(scope),\n * }\n * ```\n */\nexport async function prefetchQueries(\n queries: ReadonlyArray<PrefetchableQuery>,\n config: PrefetchQueriesConfig,\n): Promise<void> {\n const { scope } = config\n await Promise.all(queries.map((q) => allSettled(q.prefetch, { scope })))\n await Promise.all(queries.map((q) => allSettled(q.mounted, { scope })))\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effector-tanstack-query/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Effector bindings for TanStack Query — core factories (createQuery, createMutation, createInfiniteQuery)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ilya Agarkov <ilya.al.ag@gmail.com>",
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,11 @@ export { createMutation } from './createMutation'
|
|
|
4
4
|
export { createInvalidate } from './createInvalidate'
|
|
5
5
|
export type { CreateInvalidateOptions } from './createInvalidate'
|
|
6
6
|
export { $queryClient, setQueryClient } from './queryClient'
|
|
7
|
+
export { prefetchQueries } from './prefetchQueries'
|
|
8
|
+
export type {
|
|
9
|
+
PrefetchableQuery,
|
|
10
|
+
PrefetchQueriesConfig,
|
|
11
|
+
} from './prefetchQueries'
|
|
7
12
|
export type {
|
|
8
13
|
CreateInfiniteQueryOptions,
|
|
9
14
|
CreateMutationOptions,
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { allSettled } from 'effector'
|
|
2
|
+
import type { EventCallable, Scope } from 'effector'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Structural shape of any factory result that exposes the two SSR
|
|
6
|
+
* lifecycle events. Both `QueryResult` and `InfiniteQueryResult` satisfy
|
|
7
|
+
* this without forcing the caller to widen their `TData` / `TError` type
|
|
8
|
+
* parameters.
|
|
9
|
+
*/
|
|
10
|
+
export interface PrefetchableQuery {
|
|
11
|
+
prefetch: EventCallable<void>
|
|
12
|
+
mounted: EventCallable<void>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface PrefetchQueriesConfig {
|
|
16
|
+
/** Scope to run the lifecycle events in. Required — `allSettled` cannot
|
|
17
|
+
* await unit triggers outside of a scope. */
|
|
18
|
+
scope: Scope
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Server-side helper that fills **both** SSR layers for a set of queries:
|
|
23
|
+
*
|
|
24
|
+
* 1. `await allSettled(q.prefetch, { scope })` for each query — awaits
|
|
25
|
+
* `queryClient.fetchQuery(...)` so by the time the promise resolves
|
|
26
|
+
* the cache holds the data.
|
|
27
|
+
* 2. `await allSettled(q.mounted, { scope })` for each query — creates
|
|
28
|
+
* the per-scope observer; its synchronous `getCurrentResult()`
|
|
29
|
+
* dispatch reads from the now-populated cache and writes into the
|
|
30
|
+
* effector stores (`$data`, `$status`, …). This is what makes
|
|
31
|
+
* `serialize(scope)` ship populated stores, which in turn lets the
|
|
32
|
+
* server-rendered HTML show data on first paint.
|
|
33
|
+
*
|
|
34
|
+
* Skipping step 2 (calling only `prefetch`) leaves the effector stores at
|
|
35
|
+
* their defaults — `serialize(scope)` returns nothing useful, the
|
|
36
|
+
* server-rendered HTML shows loading, and the user sees a flash on
|
|
37
|
+
* hydration. This helper exists so that bug is impossible to write.
|
|
38
|
+
*
|
|
39
|
+
* Both phases run in parallel within themselves (`Promise.all`) but
|
|
40
|
+
* sequentially across phases (`mounted` must see a populated cache).
|
|
41
|
+
*
|
|
42
|
+
* Snapshot the layers yourself afterwards — `dehydrate(queryClient)` for
|
|
43
|
+
* the cache and `serialize(scope)` for the stores — and ship both to the
|
|
44
|
+
* client (e.g. via `<HydrationBoundary state={...}>` + `<EffectorNext
|
|
45
|
+
* values={...}>` or `fork({ values: ... })`).
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const queryClient = new QueryClient()
|
|
50
|
+
* const scope = fork({ values: [[$queryClient, queryClient]] })
|
|
51
|
+
*
|
|
52
|
+
* await prefetchQueries([listQuery, pokemonQuery], { scope })
|
|
53
|
+
*
|
|
54
|
+
* return {
|
|
55
|
+
* dehydratedQueryClient: dehydrate(queryClient),
|
|
56
|
+
* serializedScope: serialize(scope),
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export async function prefetchQueries(
|
|
61
|
+
queries: ReadonlyArray<PrefetchableQuery>,
|
|
62
|
+
config: PrefetchQueriesConfig,
|
|
63
|
+
): Promise<void> {
|
|
64
|
+
const { scope } = config
|
|
65
|
+
await Promise.all(queries.map((q) => allSettled(q.prefetch, { scope })))
|
|
66
|
+
await Promise.all(queries.map((q) => allSettled(q.mounted, { scope })))
|
|
67
|
+
}
|