@lewebsimple/nuxt-graphql 0.6.17 → 0.6.19
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/module.json +1 -1
- package/dist/module.mjs +1 -1
- package/dist/runtime/app/composables/useAsyncGraphQLQuery.d.ts +2 -1
- package/dist/runtime/app/composables/useAsyncGraphQLQuery.js +14 -9
- package/dist/runtime/app/composables/useGraphQLCache.client.d.ts +9 -4
- package/dist/runtime/app/composables/useGraphQLCache.client.js +61 -21
- package/dist/runtime/app/composables/useGraphQLLoadMore.d.ts +2 -2
- package/dist/runtime/app/composables/useGraphQLMutation.d.ts +1 -1
- package/dist/runtime/app/lib/cache.d.ts +63 -6
- package/dist/runtime/app/lib/cache.js +63 -7
- package/dist/runtime/app/plugins/execute-graphql.d.ts +5 -1
- package/dist/runtime/app/plugins/graphql-sse.client.d.ts +5 -1
- package/package.json +7 -7
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import type { CacheConfig, IsEmptyObject } from "../../shared/lib/types.js";
|
|
|
6
6
|
type UseAsyncGraphQLQueryOptions<TName extends QueryName, TTransformed = ResultOf<TName>> = Omit<AsyncDataOptions<ResultOf<TName>>, "transform" | "pick"> & {
|
|
7
7
|
transform?: (input: ResultOf<TName>) => TTransformed;
|
|
8
8
|
cache?: Partial<CacheConfig>;
|
|
9
|
+
scope?: string;
|
|
9
10
|
};
|
|
10
11
|
/**
|
|
11
12
|
* Async GraphQL query composable with caching support.
|
|
@@ -14,5 +15,5 @@ type UseAsyncGraphQLQueryOptions<TName extends QueryName, TTransformed = ResultO
|
|
|
14
15
|
* @param args Operation variables (if any) and optional HTTP headers.
|
|
15
16
|
* @returns Nuxt AsyncData wrapper for the query result.
|
|
16
17
|
*/
|
|
17
|
-
export declare function useAsyncGraphQLQuery<TName extends QueryName, TTransformed = ResultOf<TName>>(operationName: TName, ...args: IsEmptyObject<VariablesOf<TName>> extends true ? [variables?: MaybeRefOrGetter<VariablesOf<TName>>, options?: UseAsyncGraphQLQueryOptions<TName, TTransformed>] : [variables: MaybeRefOrGetter<VariablesOf<TName>>, options?: UseAsyncGraphQLQueryOptions<TName, TTransformed>]): AsyncData<TTransformed | undefined, NormalizedError | undefined>;
|
|
18
|
+
export declare function useAsyncGraphQLQuery<TName extends QueryName, TTransformed extends ResultOf<TName> | Promise<ResultOf<TName>> = ResultOf<TName>>(operationName: TName, ...args: IsEmptyObject<VariablesOf<TName>> extends true ? [variables?: MaybeRefOrGetter<VariablesOf<TName>>, options?: UseAsyncGraphQLQueryOptions<TName, TTransformed>] : [variables: MaybeRefOrGetter<VariablesOf<TName>>, options?: UseAsyncGraphQLQueryOptions<TName, TTransformed>]): AsyncData<TTransformed | undefined, NormalizedError | undefined>;
|
|
18
19
|
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useAsyncData, useNuxtApp, useNuxtData, useRuntimeConfig } from "#app";
|
|
2
|
-
import { computed, toValue } from "#imports";
|
|
2
|
+
import { computed, toValue, watchEffect } from "#imports";
|
|
3
3
|
import { normalizeError } from "../../shared/lib/error.js";
|
|
4
4
|
import { getOperationDocument } from "../../shared/lib/registry.js";
|
|
5
|
-
import { getCacheKeyParts, resolveCacheConfig } from "../lib/cache.js";
|
|
5
|
+
import { getCacheKeyParts, markCacheKeyRefreshed, registerCacheKey, resolveCacheConfig, shouldBypassCache } from "../lib/cache.js";
|
|
6
6
|
import { getInFlightRequests } from "../lib/in-flight.js";
|
|
7
7
|
import { getPersistedEntry, setPersistedEntry } from "../lib/persisted.js";
|
|
8
8
|
export function useAsyncGraphQLQuery(operationName, ...args) {
|
|
@@ -11,23 +11,27 @@ export function useAsyncGraphQLQuery(operationName, ...args) {
|
|
|
11
11
|
const document = getOperationDocument(operationName);
|
|
12
12
|
const isClient = import.meta.client;
|
|
13
13
|
const { public: { graphql } } = useRuntimeConfig();
|
|
14
|
-
const { cache, transform, ...asyncDataOptions } = options ?? {};
|
|
14
|
+
const { cache, transform, scope: scopeOpt, ...asyncDataOptions } = options ?? {};
|
|
15
15
|
const cacheConfig = resolveCacheConfig(graphql.cacheConfig, cache);
|
|
16
|
-
const
|
|
16
|
+
const scope = scopeOpt ?? "global";
|
|
17
|
+
const cacheKey = computed(() => getCacheKeyParts(cacheConfig, scope, operationName, toValue(variables)).key);
|
|
18
|
+
watchEffect(() => {
|
|
19
|
+
registerCacheKey(cacheKey.value);
|
|
20
|
+
});
|
|
17
21
|
const inFlight = getInFlightRequests();
|
|
18
22
|
async function fetchAndPersist() {
|
|
19
23
|
const key = cacheKey.value;
|
|
20
24
|
if (inFlight.has(key)) {
|
|
21
25
|
return inFlight.get(key);
|
|
22
26
|
}
|
|
23
|
-
const promise = $executeGraphQL({ query: document, variables: toValue(variables), operationName }).then((
|
|
24
|
-
if (
|
|
25
|
-
throw
|
|
27
|
+
const promise = $executeGraphQL({ query: document, variables: toValue(variables), operationName }).then(({ data, error }) => {
|
|
28
|
+
if (error) {
|
|
29
|
+
throw error;
|
|
26
30
|
}
|
|
27
|
-
const data = result.data;
|
|
28
31
|
if (isClient && cacheConfig.ttl !== void 0) {
|
|
29
32
|
setPersistedEntry(key, data, cacheConfig.ttl);
|
|
30
33
|
}
|
|
34
|
+
markCacheKeyRefreshed(key);
|
|
31
35
|
return data;
|
|
32
36
|
});
|
|
33
37
|
inFlight.set(key, promise);
|
|
@@ -35,7 +39,8 @@ export function useAsyncGraphQLQuery(operationName, ...args) {
|
|
|
35
39
|
return promise;
|
|
36
40
|
}
|
|
37
41
|
async function asyncDataHandler() {
|
|
38
|
-
|
|
42
|
+
registerCacheKey(cacheKey.value);
|
|
43
|
+
if (cacheConfig.policy === "no-cache" || shouldBypassCache(cacheKey.value)) {
|
|
39
44
|
return await fetchAndPersist();
|
|
40
45
|
}
|
|
41
46
|
const nuxtData = useNuxtData(cacheKey.value);
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import type { QueryName, ResultOf, VariablesOf } from "#graphql/registry";
|
|
2
2
|
import type { IsEmptyObject } from "../../shared/lib/types.js";
|
|
3
|
+
type CacheWriteOptions = {
|
|
4
|
+
markFresh?: boolean;
|
|
5
|
+
};
|
|
3
6
|
/**
|
|
4
7
|
* GraphQL cache helper composable.
|
|
5
8
|
*
|
|
6
9
|
* @returns Cache manipulation helpers.
|
|
7
10
|
*/
|
|
8
|
-
export declare function useGraphQLCache(): {
|
|
9
|
-
readonly cacheConfig:
|
|
11
|
+
export declare function useGraphQLCache(scope?: string): {
|
|
12
|
+
readonly cacheConfig: import("../../shared/lib/types.js").CacheConfig;
|
|
10
13
|
readonly read: <TName extends QueryName>(operation: TName, ...args: IsEmptyObject<VariablesOf<TName>> extends true ? [variables?: VariablesOf<TName>] : [variables: VariablesOf<TName>]) => ResultOf<TName> | undefined;
|
|
11
|
-
readonly write: <TName extends QueryName>(operation: TName, variables: VariablesOf<TName>, value: ResultOf<TName> | ((current: ResultOf<TName> | undefined) => ResultOf<TName>)) => void;
|
|
12
|
-
readonly update: <TName extends QueryName>(operation: TName, variables: VariablesOf<TName>, value: ResultOf<TName> | ((current: ResultOf<TName> | undefined) => ResultOf<TName>)) => Promise<void>;
|
|
14
|
+
readonly write: <TName extends QueryName>(operation: TName, variables: VariablesOf<TName>, value: ResultOf<TName> | ((current: ResultOf<TName> | undefined) => ResultOf<TName>), options?: CacheWriteOptions) => void;
|
|
15
|
+
readonly update: <TName extends QueryName>(operation: TName, variables: VariablesOf<TName>, value: ResultOf<TName> | ((current: ResultOf<TName> | undefined) => ResultOf<TName>), options?: CacheWriteOptions) => Promise<void>;
|
|
13
16
|
readonly invalidate: <TName extends QueryName>(operation?: TName | undefined, variables?: VariablesOf<TName> | undefined) => Promise<void>;
|
|
17
|
+
readonly invalidateAllScopes: () => Promise<void>;
|
|
14
18
|
};
|
|
19
|
+
export {};
|
|
@@ -1,49 +1,89 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { refreshNuxtData, useNuxtData, useRuntimeConfig } from "#imports";
|
|
2
|
+
import {
|
|
3
|
+
forgetCacheAll,
|
|
4
|
+
forgetCacheByPrefix,
|
|
5
|
+
forgetCacheKey,
|
|
6
|
+
getCacheKeyParts,
|
|
7
|
+
getCacheKeysByPrefix,
|
|
8
|
+
invalidateAllCacheKeys,
|
|
9
|
+
invalidateCacheKey,
|
|
10
|
+
invalidateCachePrefix,
|
|
11
|
+
markCacheKeyRefreshed,
|
|
12
|
+
registerCacheKey
|
|
13
|
+
} from "../lib/cache.js";
|
|
3
14
|
import { deletePersistedByPrefix, deletePersistedEntry, getPersistedEntry, setPersistedEntry } from "../lib/persisted.js";
|
|
4
|
-
export function useGraphQLCache() {
|
|
15
|
+
export function useGraphQLCache(scope = "global") {
|
|
5
16
|
const { public: { graphql: { cacheConfig } } } = useRuntimeConfig();
|
|
17
|
+
function resolveKeyParts(operation, variables) {
|
|
18
|
+
return getCacheKeyParts(cacheConfig, scope, operation, variables ?? {});
|
|
19
|
+
}
|
|
6
20
|
function read(operation, ...args) {
|
|
7
21
|
const [variables] = args;
|
|
8
|
-
const { key } =
|
|
22
|
+
const { key } = resolveKeyParts(operation, variables);
|
|
9
23
|
const nuxtData = useNuxtData(key);
|
|
10
24
|
return nuxtData.data.value;
|
|
11
25
|
}
|
|
12
|
-
function
|
|
13
|
-
const { key } = getCacheKeyParts(cacheConfig, operation, variables);
|
|
26
|
+
function applyWrite(key, value, current, options) {
|
|
14
27
|
const nuxtData = useNuxtData(key);
|
|
15
|
-
|
|
28
|
+
const next = typeof value === "function" ? value(current) : value;
|
|
29
|
+
nuxtData.data.value = next;
|
|
30
|
+
registerCacheKey(key);
|
|
31
|
+
if (options?.markFresh) {
|
|
32
|
+
markCacheKeyRefreshed(key);
|
|
33
|
+
}
|
|
34
|
+
return next;
|
|
16
35
|
}
|
|
17
|
-
|
|
18
|
-
const { key } =
|
|
36
|
+
function write(operation, variables, value, options) {
|
|
37
|
+
const { key } = resolveKeyParts(operation, variables);
|
|
38
|
+
const nuxtData = useNuxtData(key);
|
|
39
|
+
applyWrite(key, value, nuxtData.data.value, options);
|
|
40
|
+
}
|
|
41
|
+
async function update(operation, variables, value, options) {
|
|
42
|
+
const { key } = resolveKeyParts(operation, variables);
|
|
19
43
|
const nuxtData = useNuxtData(key);
|
|
20
44
|
let current = nuxtData.data.value;
|
|
21
45
|
if (current === void 0 && cacheConfig.ttl !== void 0) {
|
|
22
46
|
current = await getPersistedEntry(key);
|
|
23
47
|
}
|
|
24
|
-
const
|
|
25
|
-
nuxtData.data.value = updated;
|
|
48
|
+
const next = applyWrite(key, value, current, options);
|
|
26
49
|
if (cacheConfig.ttl !== void 0) {
|
|
27
|
-
await setPersistedEntry(key,
|
|
50
|
+
await setPersistedEntry(key, next, cacheConfig.ttl);
|
|
28
51
|
}
|
|
29
52
|
}
|
|
30
53
|
async function invalidate(operation, variables) {
|
|
54
|
+
const { scopePrefix, opPrefix, key } = resolveKeyParts(operation, variables);
|
|
31
55
|
if (operation === void 0) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
56
|
+
invalidateCachePrefix(scopePrefix);
|
|
57
|
+
await deletePersistedByPrefix(scopePrefix);
|
|
58
|
+
const keys = getCacheKeysByPrefix(scopePrefix);
|
|
59
|
+
if (keys.length > 0) {
|
|
60
|
+
await refreshNuxtData(keys);
|
|
61
|
+
}
|
|
62
|
+
forgetCacheByPrefix(scopePrefix);
|
|
36
63
|
return;
|
|
37
64
|
}
|
|
38
65
|
if (variables === void 0) {
|
|
39
|
-
|
|
40
|
-
clearNuxtData((k) => k.startsWith(opPrefix));
|
|
66
|
+
invalidateCachePrefix(opPrefix);
|
|
41
67
|
await deletePersistedByPrefix(opPrefix);
|
|
68
|
+
const keys = getCacheKeysByPrefix(opPrefix);
|
|
69
|
+
if (keys.length > 0) {
|
|
70
|
+
await refreshNuxtData(keys);
|
|
71
|
+
}
|
|
72
|
+
forgetCacheByPrefix(opPrefix);
|
|
42
73
|
return;
|
|
43
74
|
}
|
|
44
|
-
|
|
45
|
-
clearNuxtData(key);
|
|
75
|
+
invalidateCacheKey(key);
|
|
46
76
|
await deletePersistedEntry(key);
|
|
77
|
+
await refreshNuxtData(key);
|
|
78
|
+
forgetCacheKey(key);
|
|
79
|
+
}
|
|
80
|
+
async function invalidateAllScopes() {
|
|
81
|
+
const { keyPrefix, keyVersion } = cacheConfig;
|
|
82
|
+
const rootPrefix = `${keyPrefix}:${keyVersion}:`;
|
|
83
|
+
invalidateAllCacheKeys();
|
|
84
|
+
await deletePersistedByPrefix(rootPrefix);
|
|
85
|
+
await refreshNuxtData();
|
|
86
|
+
forgetCacheAll();
|
|
47
87
|
}
|
|
48
|
-
return { cacheConfig, read, write, update, invalidate };
|
|
88
|
+
return { cacheConfig, read, write, update, invalidate, invalidateAllScopes };
|
|
49
89
|
}
|
|
@@ -10,8 +10,8 @@ type Connection<TItem> = {
|
|
|
10
10
|
};
|
|
11
11
|
export declare function useGraphQLLoadMore<TQueryName extends QueryName, TConnection extends Connection<unknown>>(queryName: TQueryName, inputVars: MaybeRef<Omit<VariablesOf<TQueryName>, "after">>, getConnection: (data?: ResultOf<TQueryName>) => TConnection | null | undefined): Promise<{
|
|
12
12
|
items: Ref<TConnection["nodes"][number][], TConnection["nodes"][number][]>;
|
|
13
|
-
pending:
|
|
14
|
-
error:
|
|
13
|
+
pending: Ref<boolean, boolean>;
|
|
14
|
+
error: Ref<import("../../shared/lib/error.js").NormalizedError | undefined, import("../../shared/lib/error.js").NormalizedError | undefined>;
|
|
15
15
|
reset: (clearProducts?: boolean) => void;
|
|
16
16
|
hasNextPage: ComputedRef<boolean>;
|
|
17
17
|
isLoadingMore: Ref<boolean, boolean>;
|
|
@@ -52,6 +52,6 @@ export type MutationOptions<TName extends MutationName, TContext = unknown> = {
|
|
|
52
52
|
* @returns Mutation state and mutate function.
|
|
53
53
|
*/
|
|
54
54
|
export declare function useGraphQLMutation<TName extends MutationName, TContext = unknown>(operationName: TName, options?: MutationOptions<TName, TContext>): {
|
|
55
|
-
pending: import("
|
|
55
|
+
pending: import("vue").Ref<boolean, boolean>;
|
|
56
56
|
mutate: (...args: IsEmptyObject<VariablesOf<TName>> extends true ? [variables?: VariablesOf<TName>] : [variables: VariablesOf<TName>]) => Promise<ExecuteGraphQLResult<ResultOf<TName>>>;
|
|
57
57
|
};
|
|
@@ -7,19 +7,76 @@ import type { CacheConfig } from "../../shared/lib/types.js";
|
|
|
7
7
|
*/
|
|
8
8
|
export declare function resolveCacheConfig(...overrides: Array<Partial<CacheConfig> | undefined>): CacheConfig;
|
|
9
9
|
type CacheKeyParts = {
|
|
10
|
-
|
|
10
|
+
rootPrefix: string;
|
|
11
|
+
scopePrefix: string;
|
|
11
12
|
opPrefix: string;
|
|
13
|
+
key: string;
|
|
12
14
|
};
|
|
13
15
|
/**
|
|
14
16
|
* Build cache key parts from config, operation name, and variables.
|
|
15
17
|
*
|
|
16
|
-
* @param {GraphQLCacheConfig}
|
|
17
|
-
* @param
|
|
18
|
-
* @param
|
|
18
|
+
* @param {GraphQLCacheConfig} config Cache configuration.
|
|
19
|
+
* @param config.keyPrefix Cache key prefix.
|
|
20
|
+
* @param config.keyVersion Cache key version.
|
|
21
|
+
* @param scope Cache scope segment.
|
|
19
22
|
* @param operationName Operation name.
|
|
20
23
|
* @param variables Operation variables.
|
|
21
|
-
* @param scope Optional cache scope segment.
|
|
22
24
|
* @returns Key parts including full key and operation prefix.
|
|
23
25
|
*/
|
|
24
|
-
export declare function getCacheKeyParts({ keyPrefix, keyVersion }: CacheConfig, operationName: string, variables: unknown
|
|
26
|
+
export declare function getCacheKeyParts({ keyPrefix, keyVersion }: CacheConfig, scope: string, operationName: string, variables: unknown): CacheKeyParts;
|
|
27
|
+
/**
|
|
28
|
+
* Register a cache key seen by async GraphQL queries.
|
|
29
|
+
*
|
|
30
|
+
* @param key Cache key.
|
|
31
|
+
*/
|
|
32
|
+
export declare function registerCacheKey(key: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Get known cache keys by prefix.
|
|
35
|
+
*
|
|
36
|
+
* @param prefix Cache key prefix.
|
|
37
|
+
* @returns Matching cache keys.
|
|
38
|
+
*/
|
|
39
|
+
export declare function getCacheKeysByPrefix(prefix: string): string[];
|
|
40
|
+
/**
|
|
41
|
+
* Mark a single cache key as invalidated.
|
|
42
|
+
*
|
|
43
|
+
* @param key Cache key.
|
|
44
|
+
*/
|
|
45
|
+
export declare function invalidateCacheKey(key: string): void;
|
|
46
|
+
/**
|
|
47
|
+
* Mark all cache keys matching a prefix as invalidated.
|
|
48
|
+
*
|
|
49
|
+
* @param prefix Cache key prefix.
|
|
50
|
+
*/
|
|
51
|
+
export declare function invalidateCachePrefix(prefix: string): void;
|
|
52
|
+
/**
|
|
53
|
+
* Mark all cache keys as invalidated.
|
|
54
|
+
*/
|
|
55
|
+
export declare function invalidateAllCacheKeys(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Mark a cache key as refreshed from network.
|
|
58
|
+
*
|
|
59
|
+
* @param key Cache key.
|
|
60
|
+
*/
|
|
61
|
+
export declare function markCacheKeyRefreshed(key: string): void;
|
|
62
|
+
/**
|
|
63
|
+
* Determine whether cache should be bypassed for this key.
|
|
64
|
+
*
|
|
65
|
+
* @param key Cache key.
|
|
66
|
+
* @returns True when invalidation is newer than the last successful network refresh.
|
|
67
|
+
*/
|
|
68
|
+
export declare function shouldBypassCache(key: string): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Remove a single cache key from all internal registries.
|
|
71
|
+
*/
|
|
72
|
+
export declare function forgetCacheKey(key: string): void;
|
|
73
|
+
/**
|
|
74
|
+
* Remove all cache keys and related metadata matching a prefix.
|
|
75
|
+
*/
|
|
76
|
+
export declare function forgetCacheByPrefix(prefix: string): void;
|
|
77
|
+
/**
|
|
78
|
+
* Clear all in-memory cache tracking metadata.
|
|
79
|
+
* Does NOT delete persisted storage.
|
|
80
|
+
*/
|
|
81
|
+
export declare function forgetCacheAll(): void;
|
|
25
82
|
export {};
|
|
@@ -8,11 +8,67 @@ const defaultCacheConfig = {
|
|
|
8
8
|
export function resolveCacheConfig(...overrides) {
|
|
9
9
|
return Object.assign({}, defaultCacheConfig, ...overrides);
|
|
10
10
|
}
|
|
11
|
-
export function getCacheKeyParts({ keyPrefix, keyVersion }, operationName, variables
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
export function getCacheKeyParts({ keyPrefix, keyVersion }, scope, operationName, variables) {
|
|
12
|
+
const rootPrefix = `${keyPrefix}:${keyVersion}:`;
|
|
13
|
+
const scopePrefix = `${rootPrefix}${scope}:`;
|
|
14
|
+
const opPrefix = `${scopePrefix}${operationName}:`;
|
|
15
|
+
const key = `${opPrefix}${hash(variables || {})}`;
|
|
16
|
+
return { rootPrefix, scopePrefix, opPrefix, key };
|
|
17
|
+
}
|
|
18
|
+
const knownCacheKeys = /* @__PURE__ */ new Set();
|
|
19
|
+
export function registerCacheKey(key) {
|
|
20
|
+
knownCacheKeys.add(key);
|
|
21
|
+
}
|
|
22
|
+
export function getCacheKeysByPrefix(prefix) {
|
|
23
|
+
return [...knownCacheKeys].filter((key) => key.startsWith(prefix));
|
|
24
|
+
}
|
|
25
|
+
const invalidatedExactAt = /* @__PURE__ */ new Map();
|
|
26
|
+
const invalidatedPrefixAt = /* @__PURE__ */ new Map();
|
|
27
|
+
const refreshedAt = /* @__PURE__ */ new Map();
|
|
28
|
+
let invalidatedAllAt = 0;
|
|
29
|
+
export function invalidateCacheKey(key) {
|
|
30
|
+
invalidatedExactAt.set(key, Date.now());
|
|
31
|
+
}
|
|
32
|
+
export function invalidateCachePrefix(prefix) {
|
|
33
|
+
invalidatedPrefixAt.set(prefix, Date.now());
|
|
34
|
+
}
|
|
35
|
+
export function invalidateAllCacheKeys() {
|
|
36
|
+
invalidatedAllAt = Date.now();
|
|
37
|
+
}
|
|
38
|
+
export function markCacheKeyRefreshed(key) {
|
|
39
|
+
refreshedAt.set(key, Date.now());
|
|
40
|
+
}
|
|
41
|
+
export function shouldBypassCache(key) {
|
|
42
|
+
const lastRefreshAt = refreshedAt.get(key) ?? 0;
|
|
43
|
+
const exactInvalidatedAt = invalidatedExactAt.get(key) ?? 0;
|
|
44
|
+
let prefixInvalidatedAt = 0;
|
|
45
|
+
for (const [prefix, timestamp] of invalidatedPrefixAt) {
|
|
46
|
+
if (key.startsWith(prefix) && timestamp > prefixInvalidatedAt) {
|
|
47
|
+
prefixInvalidatedAt = timestamp;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const latestInvalidationAt = Math.max(invalidatedAllAt, exactInvalidatedAt, prefixInvalidatedAt);
|
|
51
|
+
return latestInvalidationAt > lastRefreshAt;
|
|
52
|
+
}
|
|
53
|
+
export function forgetCacheKey(key) {
|
|
54
|
+
knownCacheKeys.delete(key);
|
|
55
|
+
invalidatedExactAt.delete(key);
|
|
56
|
+
refreshedAt.delete(key);
|
|
57
|
+
}
|
|
58
|
+
export function forgetCacheByPrefix(prefix) {
|
|
59
|
+
for (const key of knownCacheKeys) {
|
|
60
|
+
if (key.startsWith(prefix)) {
|
|
61
|
+
knownCacheKeys.delete(key);
|
|
62
|
+
invalidatedExactAt.delete(key);
|
|
63
|
+
refreshedAt.delete(key);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
invalidatedPrefixAt.delete(prefix);
|
|
67
|
+
}
|
|
68
|
+
export function forgetCacheAll() {
|
|
69
|
+
knownCacheKeys.clear();
|
|
70
|
+
invalidatedExactAt.clear();
|
|
71
|
+
invalidatedPrefixAt.clear();
|
|
72
|
+
refreshedAt.clear();
|
|
73
|
+
invalidatedAllAt = 0;
|
|
18
74
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { ExecuteGraphQLInput, ExecuteGraphQLResult, GraphQLVariables } from "../../shared/lib/types.js";
|
|
2
|
-
declare const _default:
|
|
2
|
+
declare const _default: import("#app").Plugin<{
|
|
3
|
+
executeGraphQL: <TResult = unknown, TVariables extends GraphQLVariables = GraphQLVariables>({ query, variables, operationName }: ExecuteGraphQLInput<TVariables>) => Promise<ExecuteGraphQLResult<TResult>>;
|
|
4
|
+
}> & import("#app").ObjectPlugin<{
|
|
5
|
+
executeGraphQL: <TResult = unknown, TVariables extends GraphQLVariables = GraphQLVariables>({ query, variables, operationName }: ExecuteGraphQLInput<TVariables>) => Promise<ExecuteGraphQLResult<TResult>>;
|
|
6
|
+
}>;
|
|
3
7
|
export default _default;
|
|
4
8
|
type ExecuteGraphQL = <TResult = unknown, TVariables extends GraphQLVariables = GraphQLVariables>(input: ExecuteGraphQLInput<TVariables>) => Promise<ExecuteGraphQLResult<TResult>>;
|
|
5
9
|
declare module "#app/nuxt" {
|
|
@@ -4,7 +4,11 @@ import { type Client as SSEClient } from "graphql-sse";
|
|
|
4
4
|
*
|
|
5
5
|
* @returns Nuxt plugin with SSE client provider.
|
|
6
6
|
*/
|
|
7
|
-
declare const _default:
|
|
7
|
+
declare const _default: import("#app").Plugin<{
|
|
8
|
+
getGraphQLSSEClient: () => SSEClient;
|
|
9
|
+
}> & import("#app").ObjectPlugin<{
|
|
10
|
+
getGraphQLSSEClient: () => SSEClient;
|
|
11
|
+
}>;
|
|
8
12
|
export default _default;
|
|
9
13
|
declare module "#app/nuxt" {
|
|
10
14
|
interface NuxtApp {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lewebsimple/nuxt-graphql",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.19",
|
|
4
4
|
"description": "Opinionated Nuxt module for using GraphQL",
|
|
5
5
|
"repository": "lewebsimple/nuxt-graphql",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"@graphql-tools/graphql-file-loader": "^8.1.9",
|
|
34
34
|
"@graphql-tools/load": "^8.1.8",
|
|
35
35
|
"@graphql-tools/schema": "^10.0.31",
|
|
36
|
-
"@graphql-tools/stitch": "^10.1.
|
|
36
|
+
"@graphql-tools/stitch": "^10.1.12",
|
|
37
37
|
"@nuxt/kit": "^4.3.1",
|
|
38
38
|
"defu": "^6.1.4",
|
|
39
|
-
"graphql": "^16.
|
|
39
|
+
"graphql": "^16.13.0",
|
|
40
40
|
"graphql-sse": "^2.6.0",
|
|
41
41
|
"graphql-yoga": "^5.18.0",
|
|
42
42
|
"jiti": "^2.6.1",
|
|
@@ -44,18 +44,18 @@
|
|
|
44
44
|
"unstorage": "^1.17.4"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@nuxt/devtools": "^3.2.
|
|
48
|
-
"@nuxt/eslint-config": "^1.15.
|
|
47
|
+
"@nuxt/devtools": "^3.2.2",
|
|
48
|
+
"@nuxt/eslint-config": "^1.15.2",
|
|
49
49
|
"@nuxt/module-builder": "^1.0.2",
|
|
50
50
|
"@nuxt/schema": "^4.3.1",
|
|
51
51
|
"@nuxt/test-utils": "^3.23.0",
|
|
52
52
|
"@types/node": "latest",
|
|
53
53
|
"changelogen": "^0.6.2",
|
|
54
|
-
"eslint": "^9.39.
|
|
54
|
+
"eslint": "^9.39.3",
|
|
55
55
|
"nuxt": "^4.3.1",
|
|
56
56
|
"typescript": "~5.9.3",
|
|
57
57
|
"vitest": "^4.0.18",
|
|
58
|
-
"vue-tsc": "^3.2.
|
|
58
|
+
"vue-tsc": "^3.2.5"
|
|
59
59
|
},
|
|
60
60
|
"scripts": {
|
|
61
61
|
"dev": "pnpm run dev:prepare && nuxt dev playground",
|