@remix-relay/react 1.0.0 → 2.1.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.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +24 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +17 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +32 -34
package/dist/index.d.mts
CHANGED
|
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import { SuspenseProps, PropsWithChildren } from 'react';
|
|
3
3
|
import relay, { GraphQLTaggedNode as GraphQLTaggedNode$1, PreloadFetchPolicy } from 'react-relay';
|
|
4
4
|
import { Environment, OperationType, GraphQLTaggedNode, VariablesOf, RequestParameters, Variables, CacheConfig, Observable } from 'relay-runtime';
|
|
5
|
-
import {
|
|
5
|
+
import { MetaFunction } from 'react-router';
|
|
6
6
|
import { useQueryLoaderHookType } from 'react-relay/relay-hooks/useQueryLoader';
|
|
7
7
|
|
|
8
8
|
declare function Suspense({ children, ...rest }: SuspenseProps): react_jsx_runtime.JSX.Element;
|
|
@@ -20,9 +20,9 @@ declare function RemixRelayProvider({ children }: PropsWithChildren): react_jsx_
|
|
|
20
20
|
|
|
21
21
|
declare function getCachedResponse(params: RequestParameters, variables: Variables, cacheConfig: CacheConfig): Observable<unknown> | null;
|
|
22
22
|
|
|
23
|
-
declare function metaQuery<TQuery extends OperationType>(metaFunction: (args: Parameters<
|
|
23
|
+
declare function metaQuery<TQuery extends OperationType>(metaFunction: (args: Parameters<MetaFunction>[0] & {
|
|
24
24
|
data: TQuery["response"];
|
|
25
|
-
}) => ReturnType<
|
|
25
|
+
}) => ReturnType<MetaFunction>): MetaFunction<() => {
|
|
26
26
|
preloadedQuery: {
|
|
27
27
|
response: {
|
|
28
28
|
data: TQuery["response"];
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import { SuspenseProps, PropsWithChildren } from 'react';
|
|
3
3
|
import relay, { GraphQLTaggedNode as GraphQLTaggedNode$1, PreloadFetchPolicy } from 'react-relay';
|
|
4
4
|
import { Environment, OperationType, GraphQLTaggedNode, VariablesOf, RequestParameters, Variables, CacheConfig, Observable } from 'relay-runtime';
|
|
5
|
-
import {
|
|
5
|
+
import { MetaFunction } from 'react-router';
|
|
6
6
|
import { useQueryLoaderHookType } from 'react-relay/relay-hooks/useQueryLoader';
|
|
7
7
|
|
|
8
8
|
declare function Suspense({ children, ...rest }: SuspenseProps): react_jsx_runtime.JSX.Element;
|
|
@@ -20,9 +20,9 @@ declare function RemixRelayProvider({ children }: PropsWithChildren): react_jsx_
|
|
|
20
20
|
|
|
21
21
|
declare function getCachedResponse(params: RequestParameters, variables: Variables, cacheConfig: CacheConfig): Observable<unknown> | null;
|
|
22
22
|
|
|
23
|
-
declare function metaQuery<TQuery extends OperationType>(metaFunction: (args: Parameters<
|
|
23
|
+
declare function metaQuery<TQuery extends OperationType>(metaFunction: (args: Parameters<MetaFunction>[0] & {
|
|
24
24
|
data: TQuery["response"];
|
|
25
|
-
}) => ReturnType<
|
|
25
|
+
}) => ReturnType<MetaFunction>): MetaFunction<() => {
|
|
26
26
|
preloadedQuery: {
|
|
27
27
|
response: {
|
|
28
28
|
data: TQuery["response"];
|
package/dist/index.js
CHANGED
|
@@ -41,8 +41,8 @@ __export(src_exports, {
|
|
|
41
41
|
module.exports = __toCommonJS(src_exports);
|
|
42
42
|
|
|
43
43
|
// src/Suspense.tsx
|
|
44
|
-
var import_react2 = require("
|
|
45
|
-
var
|
|
44
|
+
var import_react2 = require("react");
|
|
45
|
+
var import_react_router = require("react-router");
|
|
46
46
|
|
|
47
47
|
// src/deferred-query-context.tsx
|
|
48
48
|
var import_react = require("react");
|
|
@@ -54,20 +54,20 @@ function RemixRelayProvider({ children }) {
|
|
|
54
54
|
const [deferredQueries, setDeferredQueries] = (0, import_react.useState)(
|
|
55
55
|
null
|
|
56
56
|
);
|
|
57
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SetDeferredQueryContext
|
|
57
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SetDeferredQueryContext, { value: setDeferredQueries, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DeferredQueryContext, { value: deferredQueries, children }) });
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
// src/Suspense.tsx
|
|
61
61
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
62
62
|
function Suspense({ children, ...rest }) {
|
|
63
|
-
const [mounted, setMounted] = (0,
|
|
64
|
-
(0,
|
|
63
|
+
const [mounted, setMounted] = (0, import_react2.useState)(false);
|
|
64
|
+
(0, import_react2.useEffect)(() => {
|
|
65
65
|
if (!mounted && typeof window !== "undefined") {
|
|
66
66
|
setMounted(true);
|
|
67
67
|
}
|
|
68
68
|
}, [mounted]);
|
|
69
|
-
const deferredQuery = (0,
|
|
70
|
-
return mounted ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
69
|
+
const deferredQuery = (0, import_react2.use)(DeferredQueryContext);
|
|
70
|
+
return mounted ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react2.Suspense, { ...rest, children: deferredQuery ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_router.Await, { resolve: deferredQuery, children }) : children }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: rest.fallback });
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
// src/client-loader-query.ts
|
|
@@ -103,8 +103,7 @@ function getCachedResponse(params, variables, cacheConfig) {
|
|
|
103
103
|
const deferredFromCache = [];
|
|
104
104
|
for (let i = 0; ; i++) {
|
|
105
105
|
const deferred = responseCache.get(`${cacheKey}-${i}`, variables);
|
|
106
|
-
if (!deferred)
|
|
107
|
-
break;
|
|
106
|
+
if (!deferred) break;
|
|
108
107
|
deferredFromCache.push(deferred);
|
|
109
108
|
}
|
|
110
109
|
if (fromCache === null) {
|
|
@@ -131,19 +130,19 @@ function metaQuery(metaFunction) {
|
|
|
131
130
|
}
|
|
132
131
|
|
|
133
132
|
// src/useLoaderQuery.ts
|
|
134
|
-
var
|
|
135
|
-
var import_react5 = require("react");
|
|
133
|
+
var import_react3 = require("react");
|
|
136
134
|
var import_react_dom = require("react-dom");
|
|
137
135
|
var import_react_relay2 = __toESM(require("react-relay"));
|
|
136
|
+
var import_react_router2 = require("react-router");
|
|
138
137
|
var import_tiny_invariant = __toESM(require("tiny-invariant"));
|
|
139
138
|
var { usePreloadedQuery, useQueryLoader, useRelayEnvironment } = import_react_relay2.default;
|
|
140
139
|
function useLoaderQuery(query, fetchPolicy = "network-only") {
|
|
141
|
-
const loaderData = (0,
|
|
140
|
+
const loaderData = (0, import_react_router2.useLoaderData)();
|
|
142
141
|
const preloadedQuery = "preloadedQuery" in loaderData ? loaderData.preloadedQuery : null;
|
|
143
142
|
const deferredQueries = "deferredQueries" in loaderData ? loaderData.deferredQueries : null;
|
|
144
|
-
const [deferredResult, setDeferredResult] = (0,
|
|
145
|
-
const setDeferredQueries = (0,
|
|
146
|
-
(0,
|
|
143
|
+
const [deferredResult, setDeferredResult] = (0, import_react3.useState)(preloadedQuery);
|
|
144
|
+
const setDeferredQueries = (0, import_react3.use)(SetDeferredQueryContext);
|
|
145
|
+
(0, import_react3.useEffect)(() => {
|
|
147
146
|
if (deferredQueries) {
|
|
148
147
|
setDeferredQueries(
|
|
149
148
|
deferredQueries.then(async (deferredResults) => {
|
|
@@ -160,17 +159,14 @@ function useLoaderQuery(query, fetchPolicy = "network-only") {
|
|
|
160
159
|
}
|
|
161
160
|
}, [deferredQueries, preloadedQuery, setDeferredQueries, setDeferredResult]);
|
|
162
161
|
const environment = useRelayEnvironment();
|
|
163
|
-
(0,
|
|
162
|
+
(0, import_react3.useMemo)(() => {
|
|
164
163
|
if (deferredResult) {
|
|
165
164
|
writePreloadedQueryToCache(deferredResult);
|
|
166
165
|
}
|
|
167
166
|
}, [deferredResult]);
|
|
168
167
|
let ref = "queryRef" in loaderData ? loaderData.queryRef : deferredResult ? {
|
|
169
168
|
environment,
|
|
170
|
-
fetchKey: `${deferredResult.params.id ?? deferredResult.params.cacheID}${
|
|
171
|
-
a = (a << 5) - a + b.charCodeAt(0);
|
|
172
|
-
return a & a;
|
|
173
|
-
}, 0)}`,
|
|
169
|
+
fetchKey: `${deferredResult.params.id ?? deferredResult.params.cacheID}${simpleHash(deferredResult.response)}`,
|
|
174
170
|
fetchPolicy,
|
|
175
171
|
isDisposed: false,
|
|
176
172
|
name: deferredResult.params.name,
|
|
@@ -179,10 +175,9 @@ function useLoaderQuery(query, fetchPolicy = "network-only") {
|
|
|
179
175
|
dispose: () => {
|
|
180
176
|
}
|
|
181
177
|
} : null;
|
|
182
|
-
(0, import_tiny_invariant.default)(ref);
|
|
178
|
+
(0, import_tiny_invariant.default)(ref, "Missing queryRef");
|
|
183
179
|
const [queryRef, loadQuery2, disposeQuery] = useQueryLoader(query);
|
|
184
|
-
if (queryRef)
|
|
185
|
-
ref = queryRef;
|
|
180
|
+
if (queryRef) ref = queryRef;
|
|
186
181
|
const reloadQuery = (variables, options = { fetchPolicy: "store-and-network" }) => loadQuery2(variables, options);
|
|
187
182
|
const data = usePreloadedQuery(query, ref);
|
|
188
183
|
return [data, reloadQuery, disposeQuery];
|
|
@@ -195,6 +190,12 @@ function writePreloadedQueryToCache(preloadedQueryObject) {
|
|
|
195
190
|
preloadedQueryObject.response
|
|
196
191
|
);
|
|
197
192
|
}
|
|
193
|
+
function simpleHash(input) {
|
|
194
|
+
return JSON.stringify(input).split("").reduce((a, b) => {
|
|
195
|
+
a = (a << 5) - a + b.charCodeAt(0);
|
|
196
|
+
return a & a;
|
|
197
|
+
}, 0);
|
|
198
|
+
}
|
|
198
199
|
// Annotate the CommonJS export names for ESM import in node:
|
|
199
200
|
0 && (module.exports = {
|
|
200
201
|
RemixRelayProvider,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/Suspense.tsx","../src/deferred-query-context.tsx","../src/client-loader-query.ts","../src/get-cached-response.ts","../src/meta-query.ts","../src/useLoaderQuery.ts"],"sourcesContent":["export { Suspense } from \"./Suspense\";\nexport { clientLoaderQuery, getClientLoaderQuery } from \"./client-loader-query\";\nexport { RemixRelayProvider } from \"./deferred-query-context\";\nexport { getCachedResponse } from \"./get-cached-response\";\nexport { metaQuery } from \"./meta-query\";\nexport { useLoaderQuery } from \"./useLoaderQuery\";\n","import { Await } from \"@remix-run/react\";\nimport {\n Suspense as ReactSuspense,\n SuspenseProps,\n useContext,\n useEffect,\n useState,\n} from \"react\";\nimport { DeferredQueryContext } from \"./deferred-query-context\";\n\nexport function Suspense({ children, ...rest }: SuspenseProps) {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n if (!mounted && typeof window !== \"undefined\") {\n setMounted(true);\n }\n }, [mounted]);\n\n const deferredQuery = useContext(DeferredQueryContext);\n\n return mounted ? (\n <ReactSuspense {...rest}>\n {deferredQuery ? (\n <Await resolve={deferredQuery}>{children}</Await>\n ) : (\n children\n )}\n </ReactSuspense>\n ) : (\n <>{rest.fallback}</>\n );\n}\n","import type { Dispatch, PropsWithChildren, SetStateAction } from \"react\";\nimport { createContext, useState } from \"react\";\n\nexport const DeferredQueryContext = createContext<Promise<any> | null>(null);\nexport const SetDeferredQueryContext = createContext<\n Dispatch<SetStateAction<Promise<any> | null>>\n>(() => {});\n\nexport function RemixRelayProvider({ children }: PropsWithChildren) {\n const [deferredQueries, setDeferredQueries] = useState<Promise<any> | null>(\n null,\n );\n\n return (\n <SetDeferredQueryContext.Provider value={setDeferredQueries}>\n <DeferredQueryContext.Provider value={deferredQueries}>\n {children}\n </DeferredQueryContext.Provider>\n </SetDeferredQueryContext.Provider>\n );\n}\n","import relay from \"react-relay\";\nimport type {\n Environment,\n GraphQLTaggedNode,\n OperationType,\n VariablesOf,\n} from \"relay-runtime\";\n\nconst { fetchQuery, loadQuery } = relay;\n\nexport function getClientLoaderQuery(environment: Environment) {\n return async <TQuery extends OperationType>(\n query: GraphQLTaggedNode,\n variables: VariablesOf<TQuery>,\n ) => clientLoaderQuery(environment, query, variables);\n}\n\nexport async function clientLoaderQuery<TQuery extends OperationType>(\n environment: Environment,\n query: GraphQLTaggedNode,\n variables: VariablesOf<TQuery>,\n) {\n const data = await fetchQuery<TQuery>(environment, query, variables, {\n fetchPolicy: \"store-or-network\",\n }).toPromise();\n\n const queryRef = loadQuery<TQuery>(environment, query, variables, {\n fetchPolicy: \"store-only\",\n });\n\n return { queryRef, data };\n}\n","import type {\n CacheConfig,\n GraphQLResponse,\n RequestParameters,\n Variables,\n} from \"relay-runtime\";\nimport { Observable, QueryResponseCache } from \"relay-runtime\";\n\nexport const responseCache: QueryResponseCache = new QueryResponseCache({\n size: 100,\n ttl: 5000,\n});\n\nexport function getCachedResponse(\n params: RequestParameters,\n variables: Variables,\n cacheConfig: CacheConfig,\n) {\n const isQuery = params.operationKind === \"query\";\n const cacheKey = params.id ?? params.cacheID;\n const forceFetch = cacheConfig && cacheConfig.force;\n\n if (responseCache === null || !isQuery || forceFetch) {\n return null;\n }\n\n const fromCache = responseCache.get(cacheKey, variables);\n\n const deferredFromCache: GraphQLResponse[] = [];\n\n for (let i = 0; ; i++) {\n const deferred = responseCache.get(`${cacheKey}-${i}`, variables);\n if (!deferred) break;\n deferredFromCache.push(deferred);\n }\n\n if (fromCache === null) {\n return null;\n }\n\n return Observable.create((sink) => {\n sink.next(fromCache);\n\n for (const deferred of deferredFromCache) {\n sink.next(deferred);\n }\n\n sink.complete();\n });\n}\n","/* eslint-disable no-unused-vars */\nimport type { ServerRuntimeMetaFunction } from \"@remix-run/server-runtime\";\nimport type { OperationType } from \"relay-runtime\";\n\nexport function metaQuery<TQuery extends OperationType>(\n metaFunction: (\n args: Parameters<ServerRuntimeMetaFunction>[0] & {\n data: TQuery[\"response\"];\n },\n ) => ReturnType<ServerRuntimeMetaFunction>,\n): ServerRuntimeMetaFunction<\n () =>\n | { preloadedQuery: { response: { data: TQuery[\"response\"] } } }\n | { data: TQuery[\"response\"] }\n> {\n return ({ data, ...rest }) => {\n const metaData: TQuery[\"response\"] =\n data && \"data\" in data\n ? data.data\n : data && \"preloadedQuery\" in data\n ? (data.preloadedQuery.response as { data: TQuery[\"response\"] }).data\n : null;\n\n return metaFunction({\n data: metaData,\n ...rest,\n });\n };\n}\n","import type { TypedDeferredData } from \"@remix-run/node\";\nimport { useLoaderData } from \"@remix-run/react\";\nimport { useContext, useEffect, useMemo, useState } from \"react\";\nimport { flushSync } from \"react-dom\";\nimport type {\n GraphQLTaggedNode,\n PreloadFetchPolicy,\n PreloadedQuery,\n} from \"react-relay\";\nimport relay from \"react-relay\";\nimport type { useQueryLoaderHookType } from \"react-relay/relay-hooks/useQueryLoader\";\nimport type {\n ConcreteRequest,\n GraphQLResponse,\n OperationType,\n VariablesOf,\n} from \"relay-runtime\";\nimport invariant from \"tiny-invariant\";\nimport { SetDeferredQueryContext } from \"./deferred-query-context\";\nimport { responseCache } from \"./get-cached-response\";\n\nconst { usePreloadedQuery, useQueryLoader, useRelayEnvironment } = relay;\n\nexport type SerializablePreloadedQuery<TQuery extends OperationType> = {\n params: ConcreteRequest[\"params\"];\n variables: VariablesOf<TQuery>;\n response: GraphQLResponse;\n};\n\nexport function useLoaderQuery<TQuery extends OperationType>(\n query: GraphQLTaggedNode,\n fetchPolicy: PreloadFetchPolicy = \"network-only\",\n): [\n TQuery[\"response\"],\n useQueryLoaderHookType<TQuery>[1],\n useQueryLoaderHookType<TQuery>[2],\n] {\n const loaderData = useLoaderData<\n () => Promise<\n | TypedDeferredData<{\n preloadedQuery: SerializablePreloadedQuery<TQuery>;\n deferredQueries: Promise<SerializablePreloadedQuery<TQuery>[]>;\n }>\n | { queryRef: PreloadedQuery<TQuery> }\n >\n >();\n\n const preloadedQuery =\n \"preloadedQuery\" in loaderData\n ? (loaderData.preloadedQuery as unknown as SerializablePreloadedQuery<TQuery>)\n : null;\n\n const deferredQueries =\n \"deferredQueries\" in loaderData\n ? (loaderData.deferredQueries as unknown as Promise<\n SerializablePreloadedQuery<TQuery>[]\n >)\n : null;\n\n const [deferredResult, setDeferredResult] = useState(preloadedQuery);\n\n const setDeferredQueries = useContext(SetDeferredQueryContext);\n\n useEffect(() => {\n if (deferredQueries) {\n setDeferredQueries(\n deferredQueries.then(async (deferredResults) => {\n deferredResults.forEach((result) => {\n flushSync(() => {\n setDeferredResult(\n result as unknown as SerializablePreloadedQuery<TQuery>,\n );\n });\n });\n\n return deferredResults;\n }),\n );\n }\n }, [deferredQueries, preloadedQuery, setDeferredQueries, setDeferredResult]);\n\n const environment = useRelayEnvironment();\n\n useMemo(() => {\n if (deferredResult) {\n writePreloadedQueryToCache(deferredResult);\n }\n }, [deferredResult]);\n\n let ref: PreloadedQuery<TQuery> | null =\n \"queryRef\" in loaderData\n ? (loaderData.queryRef as unknown as PreloadedQuery<TQuery>)\n : deferredResult\n ? {\n environment,\n fetchKey: `${\n deferredResult.params.id ?? deferredResult.params.cacheID\n }${JSON.stringify(deferredResult.response)\n .split(\"\")\n .reduce((a, b) => {\n a = (a << 5) - a + b.charCodeAt(0);\n return a & a;\n }, 0)}`,\n fetchPolicy,\n isDisposed: false,\n name: deferredResult.params.name,\n kind: \"PreloadedQuery\",\n variables: deferredResult.variables,\n dispose: () => {},\n }\n : null;\n\n invariant(ref);\n\n const [queryRef, loadQuery, disposeQuery] = useQueryLoader<TQuery>(query);\n\n if (queryRef) ref = queryRef;\n\n const reloadQuery: typeof loadQuery = (\n variables,\n options = { fetchPolicy: \"store-and-network\" },\n ) => loadQuery(variables, options);\n\n const data = usePreloadedQuery<TQuery>(query, ref);\n\n return [data, reloadQuery, disposeQuery];\n}\n\nfunction writePreloadedQueryToCache<TQuery extends OperationType>(\n preloadedQueryObject: SerializablePreloadedQuery<TQuery>,\n) {\n let cacheKey =\n preloadedQueryObject.params.id ?? preloadedQueryObject.params.cacheID;\n\n responseCache?.set(\n cacheKey,\n preloadedQueryObject.variables,\n preloadedQueryObject.response,\n );\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","ReactSuspense","relay","import_react","import_react_relay","relay","invariant","loadQuery"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/Suspense.tsx","../src/deferred-query-context.tsx","../src/client-loader-query.ts","../src/get-cached-response.ts","../src/meta-query.ts","../src/useLoaderQuery.ts"],"sourcesContent":["export { Suspense } from \"./Suspense\";\nexport { clientLoaderQuery, getClientLoaderQuery } from \"./client-loader-query\";\nexport { RemixRelayProvider } from \"./deferred-query-context\";\nexport { getCachedResponse } from \"./get-cached-response\";\nexport { metaQuery } from \"./meta-query\";\nexport { useLoaderQuery } from \"./useLoaderQuery\";\n","import {\n Suspense as ReactSuspense,\n SuspenseProps,\n use,\n useEffect,\n useState,\n} from \"react\";\nimport { Await } from \"react-router\";\nimport { DeferredQueryContext } from \"./deferred-query-context\";\n\nexport function Suspense({ children, ...rest }: SuspenseProps) {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n if (!mounted && typeof window !== \"undefined\") {\n setMounted(true);\n }\n }, [mounted]);\n\n const deferredQuery = use(DeferredQueryContext);\n\n return mounted ? (\n <ReactSuspense {...rest}>\n {deferredQuery ? (\n <Await resolve={deferredQuery}>{children}</Await>\n ) : (\n children\n )}\n </ReactSuspense>\n ) : (\n <>{rest.fallback}</>\n );\n}\n","import type { Dispatch, PropsWithChildren, SetStateAction } from \"react\";\nimport { createContext, useState } from \"react\";\n\nexport const DeferredQueryContext = createContext<Promise<any> | null>(null);\nexport const SetDeferredQueryContext = createContext<\n Dispatch<SetStateAction<Promise<any> | null>>\n>(() => {});\n\nexport function RemixRelayProvider({ children }: PropsWithChildren) {\n const [deferredQueries, setDeferredQueries] = useState<Promise<any> | null>(\n null,\n );\n\n return (\n <SetDeferredQueryContext value={setDeferredQueries}>\n <DeferredQueryContext value={deferredQueries}>\n {children}\n </DeferredQueryContext>\n </SetDeferredQueryContext>\n );\n}\n","import relay from \"react-relay\";\nimport type {\n Environment,\n GraphQLTaggedNode,\n OperationType,\n VariablesOf,\n} from \"relay-runtime\";\n\nconst { fetchQuery, loadQuery } = relay;\n\nexport function getClientLoaderQuery(environment: Environment) {\n return async <TQuery extends OperationType>(\n query: GraphQLTaggedNode,\n variables: VariablesOf<TQuery>,\n ) => clientLoaderQuery(environment, query, variables);\n}\n\nexport async function clientLoaderQuery<TQuery extends OperationType>(\n environment: Environment,\n query: GraphQLTaggedNode,\n variables: VariablesOf<TQuery>,\n) {\n const data = await fetchQuery<TQuery>(environment, query, variables, {\n fetchPolicy: \"store-or-network\",\n }).toPromise();\n\n const queryRef = loadQuery<TQuery>(environment, query, variables, {\n fetchPolicy: \"store-only\",\n });\n\n return { queryRef, data };\n}\n","import type {\n CacheConfig,\n GraphQLResponse,\n RequestParameters,\n Variables,\n} from \"relay-runtime\";\nimport { Observable, QueryResponseCache } from \"relay-runtime\";\n\nexport const responseCache: QueryResponseCache = new QueryResponseCache({\n size: 100,\n ttl: 5000,\n});\n\nexport function getCachedResponse(\n params: RequestParameters,\n variables: Variables,\n cacheConfig: CacheConfig,\n) {\n const isQuery = params.operationKind === \"query\";\n const cacheKey = params.id ?? params.cacheID;\n const forceFetch = cacheConfig && cacheConfig.force;\n\n if (responseCache === null || !isQuery || forceFetch) {\n return null;\n }\n\n const fromCache = responseCache.get(cacheKey, variables);\n\n const deferredFromCache: GraphQLResponse[] = [];\n\n for (let i = 0; ; i++) {\n const deferred = responseCache.get(`${cacheKey}-${i}`, variables);\n if (!deferred) break;\n deferredFromCache.push(deferred);\n }\n\n if (fromCache === null) {\n return null;\n }\n\n return Observable.create((sink) => {\n sink.next(fromCache);\n\n for (const deferred of deferredFromCache) {\n sink.next(deferred);\n }\n\n sink.complete();\n });\n}\n","/* eslint-disable no-unused-vars */\nimport type { MetaFunction } from \"react-router\";\nimport type { OperationType } from \"relay-runtime\";\n\nexport function metaQuery<TQuery extends OperationType>(\n metaFunction: (\n args: Parameters<MetaFunction>[0] & {\n data: TQuery[\"response\"];\n },\n ) => ReturnType<MetaFunction>,\n): MetaFunction<\n () =>\n | { preloadedQuery: { response: { data: TQuery[\"response\"] } } }\n | { data: TQuery[\"response\"] }\n> {\n return ({ data, ...rest }) => {\n const metaData: TQuery[\"response\"] =\n data && \"data\" in data\n ? data.data\n : data && \"preloadedQuery\" in data\n ? (data.preloadedQuery.response as { data: TQuery[\"response\"] }).data\n : null;\n\n return metaFunction({\n data: metaData,\n ...rest,\n });\n };\n}\n","import { use, useEffect, useMemo, useState } from \"react\";\nimport { flushSync } from \"react-dom\";\nimport type {\n GraphQLTaggedNode,\n PreloadFetchPolicy,\n PreloadedQuery,\n} from \"react-relay\";\nimport relay from \"react-relay\";\nimport type { useQueryLoaderHookType } from \"react-relay/relay-hooks/useQueryLoader\";\nimport { useLoaderData } from \"react-router\";\nimport type {\n ConcreteRequest,\n GraphQLResponse,\n OperationType,\n VariablesOf,\n} from \"relay-runtime\";\nimport invariant from \"tiny-invariant\";\nimport { SetDeferredQueryContext } from \"./deferred-query-context\";\nimport { responseCache } from \"./get-cached-response\";\n\nconst { usePreloadedQuery, useQueryLoader, useRelayEnvironment } = relay;\n\nexport type SerializablePreloadedQuery<TQuery extends OperationType> = {\n params: ConcreteRequest[\"params\"];\n variables: VariablesOf<TQuery>;\n response: GraphQLResponse;\n};\n\nexport function useLoaderQuery<TQuery extends OperationType>(\n query: GraphQLTaggedNode,\n fetchPolicy: PreloadFetchPolicy = \"network-only\",\n): [\n TQuery[\"response\"],\n useQueryLoaderHookType<TQuery>[1],\n useQueryLoaderHookType<TQuery>[2],\n] {\n const loaderData = useLoaderData<\n () => Promise<\n | {\n preloadedQuery: SerializablePreloadedQuery<TQuery>;\n deferredQueries: Promise<SerializablePreloadedQuery<TQuery>[]>;\n }\n | { queryRef: PreloadedQuery<TQuery> }\n >\n >();\n\n const preloadedQuery =\n \"preloadedQuery\" in loaderData\n ? (loaderData.preloadedQuery as unknown as SerializablePreloadedQuery<TQuery>)\n : null;\n\n const deferredQueries =\n \"deferredQueries\" in loaderData\n ? (loaderData.deferredQueries as unknown as Promise<\n SerializablePreloadedQuery<TQuery>[]\n >)\n : null;\n\n const [deferredResult, setDeferredResult] = useState(preloadedQuery);\n\n const setDeferredQueries = use(SetDeferredQueryContext);\n\n useEffect(() => {\n if (deferredQueries) {\n setDeferredQueries(\n deferredQueries.then(async (deferredResults) => {\n deferredResults.forEach((result) => {\n flushSync(() => {\n setDeferredResult(\n result as unknown as SerializablePreloadedQuery<TQuery>,\n );\n });\n });\n\n return deferredResults;\n }),\n );\n }\n }, [deferredQueries, preloadedQuery, setDeferredQueries, setDeferredResult]);\n\n const environment = useRelayEnvironment();\n\n useMemo(() => {\n if (deferredResult) {\n writePreloadedQueryToCache(deferredResult);\n }\n }, [deferredResult]);\n\n let ref: PreloadedQuery<TQuery> | null =\n \"queryRef\" in loaderData\n ? (loaderData.queryRef as unknown as PreloadedQuery<TQuery>)\n : deferredResult\n ? {\n environment,\n fetchKey: `${\n deferredResult.params.id ?? deferredResult.params.cacheID\n }${simpleHash(deferredResult.response)}`,\n fetchPolicy,\n isDisposed: false,\n name: deferredResult.params.name,\n kind: \"PreloadedQuery\",\n variables: deferredResult.variables,\n dispose: () => {},\n }\n : null;\n\n invariant(ref, \"Missing queryRef\");\n\n const [queryRef, loadQuery, disposeQuery] = useQueryLoader<TQuery>(query);\n\n if (queryRef) ref = queryRef;\n\n const reloadQuery: typeof loadQuery = (\n variables,\n options = { fetchPolicy: \"store-and-network\" },\n ) => loadQuery(variables, options);\n\n const data = usePreloadedQuery<TQuery>(query, ref);\n\n return [data, reloadQuery, disposeQuery];\n}\n\nfunction writePreloadedQueryToCache<TQuery extends OperationType>(\n preloadedQueryObject: SerializablePreloadedQuery<TQuery>,\n) {\n let cacheKey =\n preloadedQueryObject.params.id ?? preloadedQueryObject.params.cacheID;\n\n responseCache?.set(\n cacheKey,\n preloadedQueryObject.variables,\n preloadedQueryObject.response,\n );\n}\n\nfunction simpleHash(input: unknown): number {\n return JSON.stringify(input)\n .split(\"\")\n .reduce((a, b) => {\n a = (a << 5) - a + b.charCodeAt(0);\n return a & a;\n }, 0);\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","ReactSuspense","relay","import_react","import_react_relay","import_react_router","relay","invariant","loadQuery"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// src/Suspense.tsx
|
|
2
|
-
import { Await } from "@remix-run/react";
|
|
3
2
|
import {
|
|
4
3
|
Suspense as ReactSuspense,
|
|
5
|
-
|
|
4
|
+
use,
|
|
6
5
|
useEffect,
|
|
7
6
|
useState as useState2
|
|
8
7
|
} from "react";
|
|
8
|
+
import { Await } from "react-router";
|
|
9
9
|
|
|
10
10
|
// src/deferred-query-context.tsx
|
|
11
11
|
import { createContext, useState } from "react";
|
|
@@ -17,7 +17,7 @@ function RemixRelayProvider({ children }) {
|
|
|
17
17
|
const [deferredQueries, setDeferredQueries] = useState(
|
|
18
18
|
null
|
|
19
19
|
);
|
|
20
|
-
return /* @__PURE__ */ jsx(SetDeferredQueryContext
|
|
20
|
+
return /* @__PURE__ */ jsx(SetDeferredQueryContext, { value: setDeferredQueries, children: /* @__PURE__ */ jsx(DeferredQueryContext, { value: deferredQueries, children }) });
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
// src/Suspense.tsx
|
|
@@ -29,7 +29,7 @@ function Suspense({ children, ...rest }) {
|
|
|
29
29
|
setMounted(true);
|
|
30
30
|
}
|
|
31
31
|
}, [mounted]);
|
|
32
|
-
const deferredQuery =
|
|
32
|
+
const deferredQuery = use(DeferredQueryContext);
|
|
33
33
|
return mounted ? /* @__PURE__ */ jsx2(ReactSuspense, { ...rest, children: deferredQuery ? /* @__PURE__ */ jsx2(Await, { resolve: deferredQuery, children }) : children }) : /* @__PURE__ */ jsx2(Fragment, { children: rest.fallback });
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -66,8 +66,7 @@ function getCachedResponse(params, variables, cacheConfig) {
|
|
|
66
66
|
const deferredFromCache = [];
|
|
67
67
|
for (let i = 0; ; i++) {
|
|
68
68
|
const deferred = responseCache.get(`${cacheKey}-${i}`, variables);
|
|
69
|
-
if (!deferred)
|
|
70
|
-
break;
|
|
69
|
+
if (!deferred) break;
|
|
71
70
|
deferredFromCache.push(deferred);
|
|
72
71
|
}
|
|
73
72
|
if (fromCache === null) {
|
|
@@ -94,10 +93,10 @@ function metaQuery(metaFunction) {
|
|
|
94
93
|
}
|
|
95
94
|
|
|
96
95
|
// src/useLoaderQuery.ts
|
|
97
|
-
import {
|
|
98
|
-
import { useContext as useContext2, useEffect as useEffect2, useMemo, useState as useState3 } from "react";
|
|
96
|
+
import { use as use2, useEffect as useEffect2, useMemo, useState as useState3 } from "react";
|
|
99
97
|
import { flushSync } from "react-dom";
|
|
100
98
|
import relay2 from "react-relay";
|
|
99
|
+
import { useLoaderData } from "react-router";
|
|
101
100
|
import invariant from "tiny-invariant";
|
|
102
101
|
var { usePreloadedQuery, useQueryLoader, useRelayEnvironment } = relay2;
|
|
103
102
|
function useLoaderQuery(query, fetchPolicy = "network-only") {
|
|
@@ -105,7 +104,7 @@ function useLoaderQuery(query, fetchPolicy = "network-only") {
|
|
|
105
104
|
const preloadedQuery = "preloadedQuery" in loaderData ? loaderData.preloadedQuery : null;
|
|
106
105
|
const deferredQueries = "deferredQueries" in loaderData ? loaderData.deferredQueries : null;
|
|
107
106
|
const [deferredResult, setDeferredResult] = useState3(preloadedQuery);
|
|
108
|
-
const setDeferredQueries =
|
|
107
|
+
const setDeferredQueries = use2(SetDeferredQueryContext);
|
|
109
108
|
useEffect2(() => {
|
|
110
109
|
if (deferredQueries) {
|
|
111
110
|
setDeferredQueries(
|
|
@@ -130,10 +129,7 @@ function useLoaderQuery(query, fetchPolicy = "network-only") {
|
|
|
130
129
|
}, [deferredResult]);
|
|
131
130
|
let ref = "queryRef" in loaderData ? loaderData.queryRef : deferredResult ? {
|
|
132
131
|
environment,
|
|
133
|
-
fetchKey: `${deferredResult.params.id ?? deferredResult.params.cacheID}${
|
|
134
|
-
a = (a << 5) - a + b.charCodeAt(0);
|
|
135
|
-
return a & a;
|
|
136
|
-
}, 0)}`,
|
|
132
|
+
fetchKey: `${deferredResult.params.id ?? deferredResult.params.cacheID}${simpleHash(deferredResult.response)}`,
|
|
137
133
|
fetchPolicy,
|
|
138
134
|
isDisposed: false,
|
|
139
135
|
name: deferredResult.params.name,
|
|
@@ -142,10 +138,9 @@ function useLoaderQuery(query, fetchPolicy = "network-only") {
|
|
|
142
138
|
dispose: () => {
|
|
143
139
|
}
|
|
144
140
|
} : null;
|
|
145
|
-
invariant(ref);
|
|
141
|
+
invariant(ref, "Missing queryRef");
|
|
146
142
|
const [queryRef, loadQuery2, disposeQuery] = useQueryLoader(query);
|
|
147
|
-
if (queryRef)
|
|
148
|
-
ref = queryRef;
|
|
143
|
+
if (queryRef) ref = queryRef;
|
|
149
144
|
const reloadQuery = (variables, options = { fetchPolicy: "store-and-network" }) => loadQuery2(variables, options);
|
|
150
145
|
const data = usePreloadedQuery(query, ref);
|
|
151
146
|
return [data, reloadQuery, disposeQuery];
|
|
@@ -158,6 +153,12 @@ function writePreloadedQueryToCache(preloadedQueryObject) {
|
|
|
158
153
|
preloadedQueryObject.response
|
|
159
154
|
);
|
|
160
155
|
}
|
|
156
|
+
function simpleHash(input) {
|
|
157
|
+
return JSON.stringify(input).split("").reduce((a, b) => {
|
|
158
|
+
a = (a << 5) - a + b.charCodeAt(0);
|
|
159
|
+
return a & a;
|
|
160
|
+
}, 0);
|
|
161
|
+
}
|
|
161
162
|
export {
|
|
162
163
|
RemixRelayProvider,
|
|
163
164
|
Suspense,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/Suspense.tsx","../src/deferred-query-context.tsx","../src/client-loader-query.ts","../src/get-cached-response.ts","../src/meta-query.ts","../src/useLoaderQuery.ts"],"sourcesContent":["import { Await } from \"@remix-run/react\";\nimport {\n Suspense as ReactSuspense,\n SuspenseProps,\n useContext,\n useEffect,\n useState,\n} from \"react\";\nimport { DeferredQueryContext } from \"./deferred-query-context\";\n\nexport function Suspense({ children, ...rest }: SuspenseProps) {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n if (!mounted && typeof window !== \"undefined\") {\n setMounted(true);\n }\n }, [mounted]);\n\n const deferredQuery = useContext(DeferredQueryContext);\n\n return mounted ? (\n <ReactSuspense {...rest}>\n {deferredQuery ? (\n <Await resolve={deferredQuery}>{children}</Await>\n ) : (\n children\n )}\n </ReactSuspense>\n ) : (\n <>{rest.fallback}</>\n );\n}\n","import type { Dispatch, PropsWithChildren, SetStateAction } from \"react\";\nimport { createContext, useState } from \"react\";\n\nexport const DeferredQueryContext = createContext<Promise<any> | null>(null);\nexport const SetDeferredQueryContext = createContext<\n Dispatch<SetStateAction<Promise<any> | null>>\n>(() => {});\n\nexport function RemixRelayProvider({ children }: PropsWithChildren) {\n const [deferredQueries, setDeferredQueries] = useState<Promise<any> | null>(\n null,\n );\n\n return (\n <SetDeferredQueryContext.Provider value={setDeferredQueries}>\n <DeferredQueryContext.Provider value={deferredQueries}>\n {children}\n </DeferredQueryContext.Provider>\n </SetDeferredQueryContext.Provider>\n );\n}\n","import relay from \"react-relay\";\nimport type {\n Environment,\n GraphQLTaggedNode,\n OperationType,\n VariablesOf,\n} from \"relay-runtime\";\n\nconst { fetchQuery, loadQuery } = relay;\n\nexport function getClientLoaderQuery(environment: Environment) {\n return async <TQuery extends OperationType>(\n query: GraphQLTaggedNode,\n variables: VariablesOf<TQuery>,\n ) => clientLoaderQuery(environment, query, variables);\n}\n\nexport async function clientLoaderQuery<TQuery extends OperationType>(\n environment: Environment,\n query: GraphQLTaggedNode,\n variables: VariablesOf<TQuery>,\n) {\n const data = await fetchQuery<TQuery>(environment, query, variables, {\n fetchPolicy: \"store-or-network\",\n }).toPromise();\n\n const queryRef = loadQuery<TQuery>(environment, query, variables, {\n fetchPolicy: \"store-only\",\n });\n\n return { queryRef, data };\n}\n","import type {\n CacheConfig,\n GraphQLResponse,\n RequestParameters,\n Variables,\n} from \"relay-runtime\";\nimport { Observable, QueryResponseCache } from \"relay-runtime\";\n\nexport const responseCache: QueryResponseCache = new QueryResponseCache({\n size: 100,\n ttl: 5000,\n});\n\nexport function getCachedResponse(\n params: RequestParameters,\n variables: Variables,\n cacheConfig: CacheConfig,\n) {\n const isQuery = params.operationKind === \"query\";\n const cacheKey = params.id ?? params.cacheID;\n const forceFetch = cacheConfig && cacheConfig.force;\n\n if (responseCache === null || !isQuery || forceFetch) {\n return null;\n }\n\n const fromCache = responseCache.get(cacheKey, variables);\n\n const deferredFromCache: GraphQLResponse[] = [];\n\n for (let i = 0; ; i++) {\n const deferred = responseCache.get(`${cacheKey}-${i}`, variables);\n if (!deferred) break;\n deferredFromCache.push(deferred);\n }\n\n if (fromCache === null) {\n return null;\n }\n\n return Observable.create((sink) => {\n sink.next(fromCache);\n\n for (const deferred of deferredFromCache) {\n sink.next(deferred);\n }\n\n sink.complete();\n });\n}\n","/* eslint-disable no-unused-vars */\nimport type { ServerRuntimeMetaFunction } from \"@remix-run/server-runtime\";\nimport type { OperationType } from \"relay-runtime\";\n\nexport function metaQuery<TQuery extends OperationType>(\n metaFunction: (\n args: Parameters<ServerRuntimeMetaFunction>[0] & {\n data: TQuery[\"response\"];\n },\n ) => ReturnType<ServerRuntimeMetaFunction>,\n): ServerRuntimeMetaFunction<\n () =>\n | { preloadedQuery: { response: { data: TQuery[\"response\"] } } }\n | { data: TQuery[\"response\"] }\n> {\n return ({ data, ...rest }) => {\n const metaData: TQuery[\"response\"] =\n data && \"data\" in data\n ? data.data\n : data && \"preloadedQuery\" in data\n ? (data.preloadedQuery.response as { data: TQuery[\"response\"] }).data\n : null;\n\n return metaFunction({\n data: metaData,\n ...rest,\n });\n };\n}\n","import type { TypedDeferredData } from \"@remix-run/node\";\nimport { useLoaderData } from \"@remix-run/react\";\nimport { useContext, useEffect, useMemo, useState } from \"react\";\nimport { flushSync } from \"react-dom\";\nimport type {\n GraphQLTaggedNode,\n PreloadFetchPolicy,\n PreloadedQuery,\n} from \"react-relay\";\nimport relay from \"react-relay\";\nimport type { useQueryLoaderHookType } from \"react-relay/relay-hooks/useQueryLoader\";\nimport type {\n ConcreteRequest,\n GraphQLResponse,\n OperationType,\n VariablesOf,\n} from \"relay-runtime\";\nimport invariant from \"tiny-invariant\";\nimport { SetDeferredQueryContext } from \"./deferred-query-context\";\nimport { responseCache } from \"./get-cached-response\";\n\nconst { usePreloadedQuery, useQueryLoader, useRelayEnvironment } = relay;\n\nexport type SerializablePreloadedQuery<TQuery extends OperationType> = {\n params: ConcreteRequest[\"params\"];\n variables: VariablesOf<TQuery>;\n response: GraphQLResponse;\n};\n\nexport function useLoaderQuery<TQuery extends OperationType>(\n query: GraphQLTaggedNode,\n fetchPolicy: PreloadFetchPolicy = \"network-only\",\n): [\n TQuery[\"response\"],\n useQueryLoaderHookType<TQuery>[1],\n useQueryLoaderHookType<TQuery>[2],\n] {\n const loaderData = useLoaderData<\n () => Promise<\n | TypedDeferredData<{\n preloadedQuery: SerializablePreloadedQuery<TQuery>;\n deferredQueries: Promise<SerializablePreloadedQuery<TQuery>[]>;\n }>\n | { queryRef: PreloadedQuery<TQuery> }\n >\n >();\n\n const preloadedQuery =\n \"preloadedQuery\" in loaderData\n ? (loaderData.preloadedQuery as unknown as SerializablePreloadedQuery<TQuery>)\n : null;\n\n const deferredQueries =\n \"deferredQueries\" in loaderData\n ? (loaderData.deferredQueries as unknown as Promise<\n SerializablePreloadedQuery<TQuery>[]\n >)\n : null;\n\n const [deferredResult, setDeferredResult] = useState(preloadedQuery);\n\n const setDeferredQueries = useContext(SetDeferredQueryContext);\n\n useEffect(() => {\n if (deferredQueries) {\n setDeferredQueries(\n deferredQueries.then(async (deferredResults) => {\n deferredResults.forEach((result) => {\n flushSync(() => {\n setDeferredResult(\n result as unknown as SerializablePreloadedQuery<TQuery>,\n );\n });\n });\n\n return deferredResults;\n }),\n );\n }\n }, [deferredQueries, preloadedQuery, setDeferredQueries, setDeferredResult]);\n\n const environment = useRelayEnvironment();\n\n useMemo(() => {\n if (deferredResult) {\n writePreloadedQueryToCache(deferredResult);\n }\n }, [deferredResult]);\n\n let ref: PreloadedQuery<TQuery> | null =\n \"queryRef\" in loaderData\n ? (loaderData.queryRef as unknown as PreloadedQuery<TQuery>)\n : deferredResult\n ? {\n environment,\n fetchKey: `${\n deferredResult.params.id ?? deferredResult.params.cacheID\n }${JSON.stringify(deferredResult.response)\n .split(\"\")\n .reduce((a, b) => {\n a = (a << 5) - a + b.charCodeAt(0);\n return a & a;\n }, 0)}`,\n fetchPolicy,\n isDisposed: false,\n name: deferredResult.params.name,\n kind: \"PreloadedQuery\",\n variables: deferredResult.variables,\n dispose: () => {},\n }\n : null;\n\n invariant(ref);\n\n const [queryRef, loadQuery, disposeQuery] = useQueryLoader<TQuery>(query);\n\n if (queryRef) ref = queryRef;\n\n const reloadQuery: typeof loadQuery = (\n variables,\n options = { fetchPolicy: \"store-and-network\" },\n ) => loadQuery(variables, options);\n\n const data = usePreloadedQuery<TQuery>(query, ref);\n\n return [data, reloadQuery, disposeQuery];\n}\n\nfunction writePreloadedQueryToCache<TQuery extends OperationType>(\n preloadedQueryObject: SerializablePreloadedQuery<TQuery>,\n) {\n let cacheKey =\n preloadedQueryObject.params.id ?? preloadedQueryObject.params.cacheID;\n\n responseCache?.set(\n cacheKey,\n preloadedQueryObject.variables,\n preloadedQueryObject.response,\n );\n}\n"],"mappings":"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","names":["useState","jsx","useState","useContext","useEffect","useState","relay","relay","useState","useContext","useEffect","loadQuery"]}
|
|
1
|
+
{"version":3,"sources":["../src/Suspense.tsx","../src/deferred-query-context.tsx","../src/client-loader-query.ts","../src/get-cached-response.ts","../src/meta-query.ts","../src/useLoaderQuery.ts"],"sourcesContent":["import {\n Suspense as ReactSuspense,\n SuspenseProps,\n use,\n useEffect,\n useState,\n} from \"react\";\nimport { Await } from \"react-router\";\nimport { DeferredQueryContext } from \"./deferred-query-context\";\n\nexport function Suspense({ children, ...rest }: SuspenseProps) {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n if (!mounted && typeof window !== \"undefined\") {\n setMounted(true);\n }\n }, [mounted]);\n\n const deferredQuery = use(DeferredQueryContext);\n\n return mounted ? (\n <ReactSuspense {...rest}>\n {deferredQuery ? (\n <Await resolve={deferredQuery}>{children}</Await>\n ) : (\n children\n )}\n </ReactSuspense>\n ) : (\n <>{rest.fallback}</>\n );\n}\n","import type { Dispatch, PropsWithChildren, SetStateAction } from \"react\";\nimport { createContext, useState } from \"react\";\n\nexport const DeferredQueryContext = createContext<Promise<any> | null>(null);\nexport const SetDeferredQueryContext = createContext<\n Dispatch<SetStateAction<Promise<any> | null>>\n>(() => {});\n\nexport function RemixRelayProvider({ children }: PropsWithChildren) {\n const [deferredQueries, setDeferredQueries] = useState<Promise<any> | null>(\n null,\n );\n\n return (\n <SetDeferredQueryContext value={setDeferredQueries}>\n <DeferredQueryContext value={deferredQueries}>\n {children}\n </DeferredQueryContext>\n </SetDeferredQueryContext>\n );\n}\n","import relay from \"react-relay\";\nimport type {\n Environment,\n GraphQLTaggedNode,\n OperationType,\n VariablesOf,\n} from \"relay-runtime\";\n\nconst { fetchQuery, loadQuery } = relay;\n\nexport function getClientLoaderQuery(environment: Environment) {\n return async <TQuery extends OperationType>(\n query: GraphQLTaggedNode,\n variables: VariablesOf<TQuery>,\n ) => clientLoaderQuery(environment, query, variables);\n}\n\nexport async function clientLoaderQuery<TQuery extends OperationType>(\n environment: Environment,\n query: GraphQLTaggedNode,\n variables: VariablesOf<TQuery>,\n) {\n const data = await fetchQuery<TQuery>(environment, query, variables, {\n fetchPolicy: \"store-or-network\",\n }).toPromise();\n\n const queryRef = loadQuery<TQuery>(environment, query, variables, {\n fetchPolicy: \"store-only\",\n });\n\n return { queryRef, data };\n}\n","import type {\n CacheConfig,\n GraphQLResponse,\n RequestParameters,\n Variables,\n} from \"relay-runtime\";\nimport { Observable, QueryResponseCache } from \"relay-runtime\";\n\nexport const responseCache: QueryResponseCache = new QueryResponseCache({\n size: 100,\n ttl: 5000,\n});\n\nexport function getCachedResponse(\n params: RequestParameters,\n variables: Variables,\n cacheConfig: CacheConfig,\n) {\n const isQuery = params.operationKind === \"query\";\n const cacheKey = params.id ?? params.cacheID;\n const forceFetch = cacheConfig && cacheConfig.force;\n\n if (responseCache === null || !isQuery || forceFetch) {\n return null;\n }\n\n const fromCache = responseCache.get(cacheKey, variables);\n\n const deferredFromCache: GraphQLResponse[] = [];\n\n for (let i = 0; ; i++) {\n const deferred = responseCache.get(`${cacheKey}-${i}`, variables);\n if (!deferred) break;\n deferredFromCache.push(deferred);\n }\n\n if (fromCache === null) {\n return null;\n }\n\n return Observable.create((sink) => {\n sink.next(fromCache);\n\n for (const deferred of deferredFromCache) {\n sink.next(deferred);\n }\n\n sink.complete();\n });\n}\n","/* eslint-disable no-unused-vars */\nimport type { MetaFunction } from \"react-router\";\nimport type { OperationType } from \"relay-runtime\";\n\nexport function metaQuery<TQuery extends OperationType>(\n metaFunction: (\n args: Parameters<MetaFunction>[0] & {\n data: TQuery[\"response\"];\n },\n ) => ReturnType<MetaFunction>,\n): MetaFunction<\n () =>\n | { preloadedQuery: { response: { data: TQuery[\"response\"] } } }\n | { data: TQuery[\"response\"] }\n> {\n return ({ data, ...rest }) => {\n const metaData: TQuery[\"response\"] =\n data && \"data\" in data\n ? data.data\n : data && \"preloadedQuery\" in data\n ? (data.preloadedQuery.response as { data: TQuery[\"response\"] }).data\n : null;\n\n return metaFunction({\n data: metaData,\n ...rest,\n });\n };\n}\n","import { use, useEffect, useMemo, useState } from \"react\";\nimport { flushSync } from \"react-dom\";\nimport type {\n GraphQLTaggedNode,\n PreloadFetchPolicy,\n PreloadedQuery,\n} from \"react-relay\";\nimport relay from \"react-relay\";\nimport type { useQueryLoaderHookType } from \"react-relay/relay-hooks/useQueryLoader\";\nimport { useLoaderData } from \"react-router\";\nimport type {\n ConcreteRequest,\n GraphQLResponse,\n OperationType,\n VariablesOf,\n} from \"relay-runtime\";\nimport invariant from \"tiny-invariant\";\nimport { SetDeferredQueryContext } from \"./deferred-query-context\";\nimport { responseCache } from \"./get-cached-response\";\n\nconst { usePreloadedQuery, useQueryLoader, useRelayEnvironment } = relay;\n\nexport type SerializablePreloadedQuery<TQuery extends OperationType> = {\n params: ConcreteRequest[\"params\"];\n variables: VariablesOf<TQuery>;\n response: GraphQLResponse;\n};\n\nexport function useLoaderQuery<TQuery extends OperationType>(\n query: GraphQLTaggedNode,\n fetchPolicy: PreloadFetchPolicy = \"network-only\",\n): [\n TQuery[\"response\"],\n useQueryLoaderHookType<TQuery>[1],\n useQueryLoaderHookType<TQuery>[2],\n] {\n const loaderData = useLoaderData<\n () => Promise<\n | {\n preloadedQuery: SerializablePreloadedQuery<TQuery>;\n deferredQueries: Promise<SerializablePreloadedQuery<TQuery>[]>;\n }\n | { queryRef: PreloadedQuery<TQuery> }\n >\n >();\n\n const preloadedQuery =\n \"preloadedQuery\" in loaderData\n ? (loaderData.preloadedQuery as unknown as SerializablePreloadedQuery<TQuery>)\n : null;\n\n const deferredQueries =\n \"deferredQueries\" in loaderData\n ? (loaderData.deferredQueries as unknown as Promise<\n SerializablePreloadedQuery<TQuery>[]\n >)\n : null;\n\n const [deferredResult, setDeferredResult] = useState(preloadedQuery);\n\n const setDeferredQueries = use(SetDeferredQueryContext);\n\n useEffect(() => {\n if (deferredQueries) {\n setDeferredQueries(\n deferredQueries.then(async (deferredResults) => {\n deferredResults.forEach((result) => {\n flushSync(() => {\n setDeferredResult(\n result as unknown as SerializablePreloadedQuery<TQuery>,\n );\n });\n });\n\n return deferredResults;\n }),\n );\n }\n }, [deferredQueries, preloadedQuery, setDeferredQueries, setDeferredResult]);\n\n const environment = useRelayEnvironment();\n\n useMemo(() => {\n if (deferredResult) {\n writePreloadedQueryToCache(deferredResult);\n }\n }, [deferredResult]);\n\n let ref: PreloadedQuery<TQuery> | null =\n \"queryRef\" in loaderData\n ? (loaderData.queryRef as unknown as PreloadedQuery<TQuery>)\n : deferredResult\n ? {\n environment,\n fetchKey: `${\n deferredResult.params.id ?? deferredResult.params.cacheID\n }${simpleHash(deferredResult.response)}`,\n fetchPolicy,\n isDisposed: false,\n name: deferredResult.params.name,\n kind: \"PreloadedQuery\",\n variables: deferredResult.variables,\n dispose: () => {},\n }\n : null;\n\n invariant(ref, \"Missing queryRef\");\n\n const [queryRef, loadQuery, disposeQuery] = useQueryLoader<TQuery>(query);\n\n if (queryRef) ref = queryRef;\n\n const reloadQuery: typeof loadQuery = (\n variables,\n options = { fetchPolicy: \"store-and-network\" },\n ) => loadQuery(variables, options);\n\n const data = usePreloadedQuery<TQuery>(query, ref);\n\n return [data, reloadQuery, disposeQuery];\n}\n\nfunction writePreloadedQueryToCache<TQuery extends OperationType>(\n preloadedQueryObject: SerializablePreloadedQuery<TQuery>,\n) {\n let cacheKey =\n preloadedQueryObject.params.id ?? preloadedQueryObject.params.cacheID;\n\n responseCache?.set(\n cacheKey,\n preloadedQueryObject.variables,\n preloadedQueryObject.response,\n );\n}\n\nfunction simpleHash(input: unknown): number {\n return JSON.stringify(input)\n .split(\"\")\n .reduce((a, b) => {\n a = (a << 5) - a + b.charCodeAt(0);\n return a & a;\n }, 0);\n}\n"],"mappings":"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","names":["useState","jsx","useState","use","useEffect","useState","relay","relay","useState","use","useEffect","loadQuery"]}
|
package/package.json
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remix-relay/react",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"author": {
|
|
6
|
-
"name": "Dan Train",
|
|
7
|
-
"url": "https://github.com/dantrain"
|
|
8
|
-
},
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "Provides Relay integration with React Router (Framework)",
|
|
9
5
|
"keywords": [
|
|
10
6
|
"Remix",
|
|
11
7
|
"Relay",
|
|
12
|
-
"React"
|
|
8
|
+
"React",
|
|
9
|
+
"React Router"
|
|
13
10
|
],
|
|
14
11
|
"homepage": "https://github.com/dantrain/remix-relay#readme",
|
|
15
12
|
"repository": {
|
|
@@ -17,10 +14,11 @@
|
|
|
17
14
|
"url": "https://github.com/dantrain/remix-relay.git"
|
|
18
15
|
},
|
|
19
16
|
"license": "MIT",
|
|
17
|
+
"author": {
|
|
18
|
+
"name": "Dan Train",
|
|
19
|
+
"url": "https://github.com/dantrain"
|
|
20
|
+
},
|
|
20
21
|
"type": "commonjs",
|
|
21
|
-
"main": "./dist/index.js",
|
|
22
|
-
"module": "./dist/index.mjs",
|
|
23
|
-
"types": "./dist/index.d.ts",
|
|
24
22
|
"exports": {
|
|
25
23
|
".": {
|
|
26
24
|
"module": "./dist/index.mjs",
|
|
@@ -31,44 +29,44 @@
|
|
|
31
29
|
"require": {
|
|
32
30
|
"types": "./dist/index.d.ts",
|
|
33
31
|
"default": "./dist/index.js"
|
|
34
|
-
}
|
|
35
|
-
"default": "./dist/index.js"
|
|
32
|
+
}
|
|
36
33
|
},
|
|
37
34
|
"./package.json": "./package.json"
|
|
38
35
|
},
|
|
36
|
+
"main": "./dist/index.js",
|
|
37
|
+
"module": "./dist/index.mjs",
|
|
38
|
+
"types": "./dist/index.d.ts",
|
|
39
39
|
"files": [
|
|
40
40
|
"dist/**"
|
|
41
41
|
],
|
|
42
|
-
"peerDependencies": {
|
|
43
|
-
"@remix-run/react": "^2.4.1",
|
|
44
|
-
"react": "^18.2.0",
|
|
45
|
-
"react-dom": "^18.2.0",
|
|
46
|
-
"react-relay": "^16.1.0",
|
|
47
|
-
"relay-runtime": "^16.1.0"
|
|
48
|
-
},
|
|
49
42
|
"dependencies": {
|
|
50
43
|
"tiny-invariant": "^1.3.3"
|
|
51
44
|
},
|
|
52
45
|
"devDependencies": {
|
|
53
|
-
"@
|
|
54
|
-
"@
|
|
55
|
-
"@
|
|
56
|
-
"@types/
|
|
57
|
-
"@types/
|
|
58
|
-
"@types/
|
|
59
|
-
"@types/react-dom": "^18.2.21",
|
|
60
|
-
"@types/react-relay": "^16.0.6",
|
|
61
|
-
"@types/relay-runtime": "^14.1.23",
|
|
46
|
+
"@types/eslint": "^9.6.1",
|
|
47
|
+
"@types/node": "^22.10.3",
|
|
48
|
+
"@types/react": "^19.0.2",
|
|
49
|
+
"@types/react-dom": "^19.0.2",
|
|
50
|
+
"@types/react-relay": "^18.2.0",
|
|
51
|
+
"@types/relay-runtime": "^18.2.3",
|
|
62
52
|
"eslint": "^8.57.0",
|
|
63
53
|
"graphql": "17.0.0-alpha.2",
|
|
54
|
+
"react": "^19.0.0",
|
|
55
|
+
"react-dom": "^19.0.0",
|
|
56
|
+
"react-relay": "^18.2.0",
|
|
57
|
+
"react-router": "^7.1.1",
|
|
58
|
+
"relay-runtime": "^18.2.0",
|
|
59
|
+
"tsup": "^8.3.5",
|
|
60
|
+
"typescript": "~5.7.2",
|
|
61
|
+
"@remix-relay/typescript-config": "0.0.0",
|
|
62
|
+
"@remix-relay/eslint-config": "0.0.0"
|
|
63
|
+
},
|
|
64
|
+
"peerDependencies": {
|
|
64
65
|
"react": "^18.2.0",
|
|
65
66
|
"react-dom": "^18.2.0",
|
|
66
|
-
"react-relay": "^16.
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"typescript": "^5.4.2",
|
|
70
|
-
"@remix-relay/eslint-config": "0.0.0",
|
|
71
|
-
"@remix-relay/typescript-config": "0.0.0"
|
|
67
|
+
"react-relay": "^16.1.0",
|
|
68
|
+
"react-router": "^7.0.0",
|
|
69
|
+
"relay-runtime": "^16.1.0"
|
|
72
70
|
},
|
|
73
71
|
"scripts": {
|
|
74
72
|
"build": "tsup",
|