@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 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 { ServerRuntimeMetaFunction } from '@remix-run/server-runtime';
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<ServerRuntimeMetaFunction>[0] & {
23
+ declare function metaQuery<TQuery extends OperationType>(metaFunction: (args: Parameters<MetaFunction>[0] & {
24
24
  data: TQuery["response"];
25
- }) => ReturnType<ServerRuntimeMetaFunction>): ServerRuntimeMetaFunction<() => {
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 { ServerRuntimeMetaFunction } from '@remix-run/server-runtime';
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<ServerRuntimeMetaFunction>[0] & {
23
+ declare function metaQuery<TQuery extends OperationType>(metaFunction: (args: Parameters<MetaFunction>[0] & {
24
24
  data: TQuery["response"];
25
- }) => ReturnType<ServerRuntimeMetaFunction>): ServerRuntimeMetaFunction<() => {
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("@remix-run/react");
45
- var import_react3 = require("react");
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.Provider, { value: setDeferredQueries, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DeferredQueryContext.Provider, { value: deferredQueries, children }) });
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, import_react3.useState)(false);
64
- (0, import_react3.useEffect)(() => {
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, import_react3.useContext)(DeferredQueryContext);
70
- return mounted ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react3.Suspense, { ...rest, children: deferredQuery ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react2.Await, { resolve: deferredQuery, children }) : children }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: rest.fallback });
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 import_react4 = require("@remix-run/react");
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, import_react4.useLoaderData)();
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, import_react5.useState)(preloadedQuery);
145
- const setDeferredQueries = (0, import_react5.useContext)(SetDeferredQueryContext);
146
- (0, import_react5.useEffect)(() => {
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, import_react5.useMemo)(() => {
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}${JSON.stringify(deferredResult.response).split("").reduce((a, b) => {
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,gBAAsB;AACtB,IAAAA,gBAMO;;;ACNP,mBAAwC;AAclC;AAZC,IAAM,2BAAuB,4BAAmC,IAAI;AACpE,IAAM,8BAA0B,4BAErC,MAAM;AAAC,CAAC;AAEH,SAAS,mBAAmB,EAAE,SAAS,GAAsB;AAClE,QAAM,CAAC,iBAAiB,kBAAkB,QAAI;AAAA,IAC5C;AAAA,EACF;AAEA,SACE,4CAAC,wBAAwB,UAAxB,EAAiC,OAAO,oBACvC,sDAAC,qBAAqB,UAArB,EAA8B,OAAO,iBACnC,UACH,GACF;AAEJ;;;ADIQ,IAAAC,sBAAA;AAdD,SAAS,SAAS,EAAE,UAAU,GAAG,KAAK,GAAkB;AAC7D,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,KAAK;AAE5C,+BAAU,MAAM;AACd,QAAI,CAAC,WAAW,OAAO,WAAW,aAAa;AAC7C,iBAAW,IAAI;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,oBAAgB,0BAAW,oBAAoB;AAErD,SAAO,UACL,6CAAC,cAAAC,UAAA,EAAe,GAAG,MAChB,0BACC,6CAAC,uBAAM,SAAS,eAAgB,UAAS,IAEzC,UAEJ,IAEA,6EAAG,eAAK,UAAS;AAErB;;;AEhCA,yBAAkB;AAQlB,IAAM,EAAE,YAAY,UAAU,IAAI,mBAAAC;AAE3B,SAAS,qBAAqB,aAA0B;AAC7D,SAAO,OACL,OACA,cACG,kBAAkB,aAAa,OAAO,SAAS;AACtD;AAEA,eAAsB,kBACpB,aACA,OACA,WACA;AACA,QAAM,OAAO,MAAM,WAAmB,aAAa,OAAO,WAAW;AAAA,IACnE,aAAa;AAAA,EACf,CAAC,EAAE,UAAU;AAEb,QAAM,WAAW,UAAkB,aAAa,OAAO,WAAW;AAAA,IAChE,aAAa;AAAA,EACf,CAAC;AAED,SAAO,EAAE,UAAU,KAAK;AAC1B;;;ACzBA,2BAA+C;AAExC,IAAM,gBAAoC,IAAI,wCAAmB;AAAA,EACtE,MAAM;AAAA,EACN,KAAK;AACP,CAAC;AAEM,SAAS,kBACd,QACA,WACA,aACA;AACA,QAAM,UAAU,OAAO,kBAAkB;AACzC,QAAM,WAAW,OAAO,MAAM,OAAO;AACrC,QAAM,aAAa,eAAe,YAAY;AAE9C,MAAI,kBAAkB,QAAQ,CAAC,WAAW,YAAY;AACpD,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,cAAc,IAAI,UAAU,SAAS;AAEvD,QAAM,oBAAuC,CAAC;AAE9C,WAAS,IAAI,KAAK,KAAK;AACrB,UAAM,WAAW,cAAc,IAAI,GAAG,QAAQ,IAAI,CAAC,IAAI,SAAS;AAChE,QAAI,CAAC;AAAU;AACf,sBAAkB,KAAK,QAAQ;AAAA,EACjC;AAEA,MAAI,cAAc,MAAM;AACtB,WAAO;AAAA,EACT;AAEA,SAAO,gCAAW,OAAO,CAAC,SAAS;AACjC,SAAK,KAAK,SAAS;AAEnB,eAAW,YAAY,mBAAmB;AACxC,WAAK,KAAK,QAAQ;AAAA,IACpB;AAEA,SAAK,SAAS;AAAA,EAChB,CAAC;AACH;;;AC7CO,SAAS,UACd,cASA;AACA,SAAO,CAAC,EAAE,MAAM,GAAG,KAAK,MAAM;AAC5B,UAAM,WACJ,QAAQ,UAAU,OACd,KAAK,OACL,QAAQ,oBAAoB,OACzB,KAAK,eAAe,SAA0C,OAC/D;AAER,WAAO,aAAa;AAAA,MAClB,MAAM;AAAA,MACN,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AACF;;;AC3BA,IAAAC,gBAA8B;AAC9B,IAAAA,gBAAyD;AACzD,uBAA0B;AAM1B,IAAAC,sBAAkB;AAQlB,4BAAsB;AAItB,IAAM,EAAE,mBAAmB,gBAAgB,oBAAoB,IAAI,oBAAAC;AAQ5D,SAAS,eACd,OACA,cAAkC,gBAKlC;AACA,QAAM,iBAAa,6BAQjB;AAEF,QAAM,iBACJ,oBAAoB,aACf,WAAW,iBACZ;AAEN,QAAM,kBACJ,qBAAqB,aAChB,WAAW,kBAGZ;AAEN,QAAM,CAAC,gBAAgB,iBAAiB,QAAI,wBAAS,cAAc;AAEnE,QAAM,yBAAqB,0BAAW,uBAAuB;AAE7D,+BAAU,MAAM;AACd,QAAI,iBAAiB;AACnB;AAAA,QACE,gBAAgB,KAAK,OAAO,oBAAoB;AAC9C,0BAAgB,QAAQ,CAAC,WAAW;AAClC,4CAAU,MAAM;AACd;AAAA,gBACE;AAAA,cACF;AAAA,YACF,CAAC;AAAA,UACH,CAAC;AAED,iBAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,GAAG,CAAC,iBAAiB,gBAAgB,oBAAoB,iBAAiB,CAAC;AAE3E,QAAM,cAAc,oBAAoB;AAExC,6BAAQ,MAAM;AACZ,QAAI,gBAAgB;AAClB,iCAA2B,cAAc;AAAA,IAC3C;AAAA,EACF,GAAG,CAAC,cAAc,CAAC;AAEnB,MAAI,MACF,cAAc,aACT,WAAW,WACZ,iBACE;AAAA,IACE;AAAA,IACA,UAAU,GACR,eAAe,OAAO,MAAM,eAAe,OAAO,OACpD,GAAG,KAAK,UAAU,eAAe,QAAQ,EACtC,MAAM,EAAE,EACR,OAAO,CAAC,GAAG,MAAM;AAChB,WAAK,KAAK,KAAK,IAAI,EAAE,WAAW,CAAC;AACjC,aAAO,IAAI;AAAA,IACb,GAAG,CAAC,CAAC;AAAA,IACP;AAAA,IACA,YAAY;AAAA,IACZ,MAAM,eAAe,OAAO;AAAA,IAC5B,MAAM;AAAA,IACN,WAAW,eAAe;AAAA,IAC1B,SAAS,MAAM;AAAA,IAAC;AAAA,EAClB,IACA;AAER,4BAAAC,SAAU,GAAG;AAEb,QAAM,CAAC,UAAUC,YAAW,YAAY,IAAI,eAAuB,KAAK;AAExE,MAAI;AAAU,UAAM;AAEpB,QAAM,cAAgC,CACpC,WACA,UAAU,EAAE,aAAa,oBAAoB,MAC1CA,WAAU,WAAW,OAAO;AAEjC,QAAM,OAAO,kBAA0B,OAAO,GAAG;AAEjD,SAAO,CAAC,MAAM,aAAa,YAAY;AACzC;AAEA,SAAS,2BACP,sBACA;AACA,MAAI,WACF,qBAAqB,OAAO,MAAM,qBAAqB,OAAO;AAEhE,iBAAe;AAAA,IACb;AAAA,IACA,qBAAqB;AAAA,IACrB,qBAAqB;AAAA,EACvB;AACF;","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
- useContext,
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.Provider, { value: setDeferredQueries, children: /* @__PURE__ */ jsx(DeferredQueryContext.Provider, { value: deferredQueries, children }) });
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 = useContext(DeferredQueryContext);
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 { useLoaderData } from "@remix-run/react";
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 = useContext2(SetDeferredQueryContext);
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}${JSON.stringify(deferredResult.response).split("").reduce((a, b) => {
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,
@@ -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
- "description": "Provides Relay integration with Remix",
4
- "version": "1.0.0",
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
- "@remix-run/node": "^2.8.1",
54
- "@remix-run/react": "^2.8.1",
55
- "@remix-run/server-runtime": "^2.8.1",
56
- "@types/eslint": "^8.56.5",
57
- "@types/node": "^20.11.25",
58
- "@types/react": "^18.2.64",
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.2.0",
67
- "relay-runtime": "^16.2.0",
68
- "tsup": "^8.0.2",
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",