graphql-persisted 0.0.7 → 20.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of graphql-persisted might be problematic. Click here for more details.

@@ -1,174 +0,0 @@
1
- import { useGraphQLQueryCache } from './context';
2
- import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
- import { ExpectedPreloadedQueryError } from './errors';
4
- import { serializeVariables } from './helpers';
5
- /**
6
- * Loads a preloaded query. Like useQuery, except it throws if the
7
- * query does not already exist in the cache.
8
- *
9
- * This hook keeps track of the value of the last render, so we're always guaranteed
10
- * to have data here, even if it's potentially stale.
11
- */
12
- export function usePreloadedPersistedQuery(query, options) {
13
- const result = usePersistedQuery(query, options);
14
- const lastData = useRef(result.data);
15
- const data = result.data ?? lastData.current;
16
- if (!data) {
17
- throw new ExpectedPreloadedQueryError(query);
18
- }
19
- useEffect(() => {
20
- if (result.data) {
21
- lastData.current = result.data;
22
- }
23
- }, [result.data]);
24
- return { ...result, data };
25
- }
26
- /**
27
- * Retrieves the persisted query from the cache,
28
- * creating it from the cache if we don't have a mounted version
29
- *
30
- * Fetches the query if:
31
- *
32
- * 1. We don't already have the operation fetched in the cache
33
- * 2. The query is considered stale based on:
34
- * a) The TTL setting
35
- * b) A mutation which invalidates the query
36
- */
37
- export function usePersistedQuery(queryName, options) {
38
- const cache = useGraphQLQueryCache();
39
- const optionsRef = useRef(options);
40
- // Ensure we always have the latest options in the optionsRef
41
- useEffect(() => {
42
- optionsRef.current = options;
43
- });
44
- // We need the variables stringified anyway to persist in the cache
45
- // simplest to just stringify them here
46
- const variableString = useMemo(() => serializeVariables(options.variables ?? {}), [options.variables]);
47
- // Read the query result from the cache
48
- const readQueryResult = useMemo(() => {
49
- return cache.tryReadQuery({
50
- queryName,
51
- variables: variableString,
52
- options: optionsRef.current,
53
- });
54
- }, [queryName, variableString, cache]);
55
- const [queryResult, setQueryResult] = useState(readQueryResult);
56
- useEffect(() => {
57
- setQueryResult(readQueryResult);
58
- }, [readQueryResult]);
59
- // If we don't have the query on mount, we fetch it.
60
- // We "subscribe" to the query so we'll receive
61
- // updates when the query values change, it becomes stale,
62
- // or it is refetched
63
- useEffect(() => {
64
- return cache.subscribeToQuery({
65
- queryResult,
66
- queryName,
67
- variables: variableString,
68
- onUpdate: setQueryResult,
69
- options: optionsRef.current,
70
- });
71
- }, [queryName, cache, queryResult, variableString]);
72
- return {
73
- ...queryResult,
74
- fetched: Boolean(queryResult),
75
- }; // GraphQLQuery.QueryRegistry[QueryName];
76
- }
77
- /**
78
- * TODO: Not working yet
79
- * Creates a container for a query that isn't fetched immediately,
80
- * but provides a loadQuery function to call
81
- */
82
- export function useLazyPersistedQuery(query) {
83
- const data = useRef(undefined);
84
- const cache = useGraphQLQueryCache();
85
- // const state = useState<'pending' | 'fetched' | 'loading' | 'stale'>('pending')
86
- const [stale, setIsStale] = useState(false);
87
- const [fetched, setIsFetched] = useState(false);
88
- const [loading, setIsLoading] = useState(false);
89
- const loadQuery = useCallback((variables) => {
90
- return new Promise((resolve, reject) => {
91
- const result = cache.readOrFetchQuery({
92
- queryName: query,
93
- variables: serializeVariables(variables),
94
- options: {},
95
- });
96
- // if ('then' in result && typeof result.then === 'function') {
97
- // Promise.resolve(result).then(resolve, reject)
98
- // }
99
- });
100
- }, [cache, query]);
101
- const errors = undefined;
102
- return {
103
- data: data.current,
104
- errors,
105
- loadQuery,
106
- loading,
107
- stale,
108
- fetched,
109
- };
110
- }
111
- /**
112
- * Executes a persisted mutation, keeping track of mutations in-flight to ensure
113
- * we don't execute the same mutation multiple times with the same values
114
- * in the same component
115
- */
116
- export function usePersistedMutation(mutationName, options) {
117
- const cache = useGraphQLQueryCache();
118
- // Keeps track of whether we're executing the mutation or not, useful
119
- // for showing loading states when we know the mutation is in-flight
120
- const [isExecuting, setIsExecuting] = useState(0);
121
- const executingRef = useRef(new Map());
122
- const optionsRef = useRef(options);
123
- useEffect(() => {
124
- optionsRef.current = options;
125
- });
126
- const execute = useCallback(async (vars, opts = {}) => {
127
- const { skipDedupeGuard = false } = opts;
128
- setIsExecuting((v) => v + 1);
129
- const inFlightVars = serializeVariables(vars);
130
- const executing = executingRef.current.get(inFlightVars);
131
- if (executing && !skipDedupeGuard) {
132
- return executing;
133
- }
134
- const inFlight = cache.executeMutation(mutationName, vars, optionsRef.current).finally(() => {
135
- if (!skipDedupeGuard) {
136
- executingRef.current.delete(inFlightVars);
137
- }
138
- setIsExecuting((v) => v - 1);
139
- });
140
- if (!skipDedupeGuard) {
141
- executingRef.current.set(inFlightVars, inFlight);
142
- }
143
- return inFlight;
144
- }, [cache, mutationName]);
145
- return {
146
- execute,
147
- isExecuting: Boolean(isExecuting > 0),
148
- };
149
- }
150
- /**
151
- * TODO: Subscription management
152
- */
153
- export function usePersistedSubscription(subscriptionName) {
154
- throw new Error(`usePersistedSubscription(${subscriptionName}) not yet supported`);
155
- }
156
- /**
157
- * Hook called when a mutation is issued, anywhere in the application.
158
- * Useful for one-off situations where we want to subscribe and refetch something
159
- * based on a mutation event
160
- */
161
- export function useOnMutation(mutation, fn) {
162
- const fnRef = useRef(fn);
163
- const cache = useGraphQLQueryCache();
164
- useEffect(() => {
165
- fnRef.current = fn;
166
- });
167
- const mutationDeps = Array.isArray(mutation) ? mutation : [mutation];
168
- useEffect(() => {
169
- return () => {
170
- //
171
- };
172
- // eslint-disable-next-line react-hooks/exhaustive-deps
173
- }, [cache, ...mutationDeps]);
174
- }
package/mjs/helpers.d.ts DELETED
@@ -1,4 +0,0 @@
1
- import type { SerializedVariables } from './types';
2
- export declare function serializeVariables(vars: object): SerializedVariables;
3
- export declare function variableString(val: SerializedVariables | object): SerializedVariables;
4
- export declare function variableObject(val: SerializedVariables | object): any;
package/mjs/helpers.js DELETED
@@ -1,10 +0,0 @@
1
- import { stringifyVariables } from 'graphql-normalize';
2
- export function serializeVariables(vars) {
3
- return stringifyVariables(vars);
4
- }
5
- export function variableString(val) {
6
- return typeof val === 'string' ? val : serializeVariables(val);
7
- }
8
- export function variableObject(val) {
9
- return typeof val === 'string' ? JSON.parse(val) : val;
10
- }
package/mjs/index.d.ts DELETED
@@ -1,8 +0,0 @@
1
- export { usePersistedQuery, usePersistedMutation, usePreloadedPersistedQuery, useOnMutation, usePersistedSubscription, } from './graphqlHooks.js';
2
- export { unwrapFragment, castFragmentData, unwrapFragmentDeep } from './fragmentData.js';
3
- export type { FragmentType, FragmentTypeUnwrapped } from './fragmentData.js';
4
- export { GraphQLQueryCache } from './GraphQLQueryCache.js';
5
- export { useGraphQLQueryCache, GraphQLQueryProvider } from './context.js';
6
- export type { GraphQLPreloadedQueryResult, GraphQLQueryResult, GraphQLQueryCacheConfig } from './types.js';
7
- import type * as GraphQLQueryTypes from './types.js';
8
- export type { GraphQLQueryTypes };
package/mjs/index.js DELETED
@@ -1,4 +0,0 @@
1
- export { usePersistedQuery, usePersistedMutation, usePreloadedPersistedQuery, useOnMutation, usePersistedSubscription, } from './graphqlHooks.js';
2
- export { unwrapFragment, castFragmentData, unwrapFragmentDeep } from './fragmentData.js';
3
- export { GraphQLQueryCache } from './GraphQLQueryCache.js';
4
- export { useGraphQLQueryCache, GraphQLQueryProvider } from './context.js';
package/mjs/types.d.ts DELETED
@@ -1,205 +0,0 @@
1
- import type { NormalizeMetaShape } from 'graphql-normalize';
2
- import type { FormattedExecutionResult, GraphQLFormattedError } from 'graphql';
3
- import type { GraphQLQueryError } from './errors';
4
- declare global {
5
- namespace GraphQLQuery {
6
- interface QueryRegistry {
7
- }
8
- interface MutationRegistry {
9
- }
10
- interface SubscriptionRegistry {
11
- }
12
- interface OperationVariables {
13
- }
14
- interface FragmentRegistry {
15
- }
16
- }
17
- }
18
- export interface GraphQLOperationStoreShape<TData = unknown> {
19
- operationType: 'query' | 'mutation' | 'subscription';
20
- operationName: string;
21
- meta: NormalizeMetaShape;
22
- data?: TData | null;
23
- errors?: ReadonlyArray<GraphQLFormattedError>;
24
- extensions?: Record<string, unknown>;
25
- variableValues: object;
26
- lastFetchedAt?: Date;
27
- stale: boolean;
28
- }
29
- export interface GraphQLCacheShape {
30
- /**
31
- * Normalized representation of the values for fields across all operations
32
- */
33
- fields: Record<string, unknown>;
34
- /**
35
- * Mapping of the operations we've seen
36
- */
37
- operations: Record<string, GraphQLOperationStoreShape<any>>;
38
- /**
39
- * "OperationName:meta" mapping
40
- */
41
- meta: Record<string, NormalizeMetaShape>;
42
- }
43
- export interface GraphQLHydratedCacheShape extends GraphQLCacheShape {
44
- hydrated: Record<string, Record<string, string>>;
45
- }
46
- export interface GraphQLQueryCacheConfig {
47
- /**
48
- * The endpoint of our GraphQL Application
49
- * @default /graphql
50
- */
51
- endpoint?: string;
52
- /**
53
- * Allows providing our own implementation of "fetch"
54
- */
55
- fetcher?: typeof fetch;
56
- /**
57
- * If we're Server-Side Rendering this code, we can serialize
58
- * the GraphQLQueryCache and send down with the client bundle,
59
- * so clients are able to re-hydrate and skip refetching
60
- */
61
- hydratedCache?: GraphQLCacheShape;
62
- /**
63
- * A mapping of graphql-normalize metadata, if we decide to provide
64
- * it rather than sending it down alongside the query
65
- *
66
- * https://github.com/tgriesser/graphql-normalize
67
- */
68
- meta?: Record<string, any>;
69
- /**
70
- * Mapping of Query Name to hash of the query to execute
71
- */
72
- persistedOperations: Record<string, string>;
73
- /**
74
- * Reverse mapping of hashes to documents, useful in development situations
75
- * where we might not have the hashes persisted on the server yet
76
- */
77
- persistedDocuments?: Record<string, string>;
78
- /**
79
- * Rather than having a mutation keep track of the queries it needs to invalidate,
80
- * the invalidateOnMutation can specify that this query becomes "invalidated" when,
81
- * a mutation, or specific mutation occurs, meaning the next time it's mounted,
82
- * it'll be refetched
83
- */
84
- queryInvalidation?: Partial<{
85
- [Q in keyof GraphQLQuery.QueryRegistry]: QueryInvalidationFn<Q>;
86
- }>;
87
- /**
88
- * When the mutation executes and returns, allows us to invalidate queries,
89
- * meaning they will be marked as "stale" and will be lazily refetched
90
- * on subsequent renders.
91
- */
92
- mutationInvalidation?: Partial<{
93
- [M in keyof GraphQLQuery.MutationRegistry]: MutationInvalidationFn<M>;
94
- }>;
95
- /**
96
- * When an error happens in the query layer, it will run through this error handler.
97
- */
98
- globalOnError?: (e: GraphQLQueryError) => void;
99
- }
100
- export type QueryInvalidationFn<Q extends keyof GraphQLQuery.QueryRegistry = keyof GraphQLQuery.QueryRegistry> = <M extends keyof GraphQLQuery.MutationRegistry>(mutationName: M, mutationVariables: GraphQLQuery.OperationVariables[M], queryVariables: GraphQLQuery.OperationVariables[Q]) => boolean;
101
- export type MutationInvalidationFn<M extends keyof GraphQLQuery.MutationRegistry = keyof GraphQLQuery.MutationRegistry> = <Q extends keyof GraphQLQuery.QueryRegistry>(queryName: Q, queryVariables: GraphQLQuery.OperationVariables[Q], mutationVariables: GraphQLQuery.OperationVariables[M]) => boolean;
102
- export interface FetchError {
103
- name: string;
104
- message: string;
105
- stack?: string;
106
- status?: number;
107
- statusText?: string;
108
- }
109
- export interface GraphQLOperationResult<Result> extends FormattedExecutionResult<Result> {
110
- fetchError?: FetchError;
111
- }
112
- export type GraphQLMutationResult<MutationName extends keyof GraphQLQuery.MutationRegistry> = GraphQLOperationResult<GraphQLQuery.MutationRegistry[MutationName]>;
113
- export interface GraphQLQueryResult<QueryName extends keyof GraphQLQuery.QueryRegistry> extends GraphQLOperationResult<GraphQLQuery.QueryRegistry[QueryName]> {
114
- fetched: boolean;
115
- }
116
- export interface GraphQLQueryLazyResult<QueryName extends keyof GraphQLQuery.QueryRegistry> extends GraphQLQueryResult<QueryName> {
117
- stale: boolean;
118
- loading: boolean;
119
- loadQuery: (variables: GraphQLQuery.OperationVariables[QueryName]) => Promise<FormattedExecutionResult<GraphQLQuery.QueryRegistry[QueryName]>>;
120
- }
121
- export interface GraphQLPreloadedQueryResult<QueryName extends keyof GraphQLQuery.QueryRegistry> extends GraphQLQueryResult<QueryName> {
122
- data: GraphQLQuery.QueryRegistry[QueryName];
123
- }
124
- export type MaybePromise<T> = T | Promise<T>;
125
- export interface GraphQLRequestBody {
126
- query?: string;
127
- variables: any;
128
- operationName?: string;
129
- extensions?: Record<string, any>;
130
- }
131
- export interface ExecutionOptions {
132
- onError?: (e: GraphQLQueryError) => void;
133
- }
134
- export type QueryVariables<QueryName extends keyof GraphQLQuery.QueryRegistry> = QueryName extends keyof GraphQLQuery.OperationVariables ? GraphQLQuery.OperationVariables[QueryName] extends {
135
- [key: string]: never;
136
- } ? {
137
- variables?: unknown;
138
- } : {
139
- variables: GraphQLQuery.OperationVariables[QueryName];
140
- } : never;
141
- export interface PersistedQueryOptions extends ExecutionOptions {
142
- /**
143
- * TTL in milliseconds for the query, after this we'll mark the query
144
- * as "stale" and revalidate
145
- */
146
- ttl?: number;
147
- /**
148
- * Poll interval to refetch the query, in milliseconds.
149
- */
150
- pollInterval?: number;
151
- }
152
- export interface ReadQueryArgs<Q extends keyof GraphQLQuery.QueryRegistry> {
153
- /**
154
- *
155
- */
156
- queryName: Q;
157
- /**
158
- *
159
- */
160
- variables: SerializedVariables | GraphQLQuery.OperationVariables[Q];
161
- /**
162
- *
163
- */
164
- options: PersistedQueryOptions;
165
- }
166
- export interface SubscribeToQueryArgs<Q extends keyof GraphQLQuery.QueryRegistry> extends ReadQueryArgs<Q> {
167
- /**
168
- * The result of readQuery, used to check whether the query is stale
169
- */
170
- queryResult?: GraphQLOperationResult<Q>;
171
- /**
172
- * Invoked when the values for this query are updated
173
- */
174
- onUpdate: (nextVal: GraphQLOperationResult<Q>) => any;
175
- }
176
- export type InvalidateQueryArgs = keyof GraphQLQuery.QueryRegistry | Array<keyof GraphQLQuery.QueryRegistry>;
177
- export type SerializedVariables = string & {
178
- __brand: 'SerializedVariables';
179
- };
180
- export type MutationTuple = {
181
- [K in keyof GraphQLQuery.MutationRegistry]: [K, GraphQLQuery.OperationVariables[K]];
182
- }[keyof GraphQLQuery.MutationRegistry];
183
- export type SubscriptionTuple = {
184
- [K in keyof GraphQLQuery.SubscriptionRegistry]: [K, GraphQLQuery.OperationVariables[K]];
185
- }[keyof GraphQLQuery.SubscriptionRegistry];
186
- export interface ExecuteMutationOptions {
187
- /**
188
- * By default, we check to ensure the mutation isn't already in-flight with the
189
- * same variables
190
- */
191
- skipDedupeGuard?: boolean;
192
- }
193
- export type PreloadQueryOptions<Q extends keyof GraphQLQuery.QueryRegistry = keyof GraphQLQuery.QueryRegistry> = {
194
- /**
195
- * If we have the operation, but we know it's stale, we'll typically refetch
196
- * and return the promise for the refetch. if "blockIfStale" is false, we will
197
- * resolve immediately and refetch in the background
198
- *
199
- * @default true
200
- */
201
- blockIfStale?: boolean;
202
- } & QueryVariables<Q>;
203
- export type HasVariables<V extends keyof GraphQLQuery.OperationVariables> = {
204
- [K in keyof GraphQLQuery.OperationVariables[V]]: GraphQLQuery.OperationVariables[V][K];
205
- }[keyof GraphQLQuery.OperationVariables[V]] extends never ? false : true;
package/mjs/types.js DELETED
@@ -1 +0,0 @@
1
- export {};