@wpnuxt/core 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wpnuxt/core",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "configKey": "wpNuxt",
5
5
  "compatibility": {
6
6
  "nuxt": ">=4.0.0"
package/dist/module.mjs CHANGED
@@ -8,7 +8,7 @@ import { parse, GraphQLError, visit, print } from 'graphql';
8
8
  import { execSync } from 'node:child_process';
9
9
  import { consola } from 'consola';
10
10
 
11
- const version = "2.1.0";
11
+ const version = "2.2.0";
12
12
 
13
13
  function createModuleError(module, message) {
14
14
  return new Error(formatErrorMessage(module, message));
@@ -190,6 +190,10 @@ function processSelections(selections, level, query, canExtract = true) {
190
190
  if (hasFragments && hasCustomFields) {
191
191
  query.hasInlineFields = true;
192
192
  }
193
+ const fieldNames = selections.filter((s) => s.kind === "Field").map((s) => s.name.value);
194
+ if (fieldNames.includes("pageInfo") && fieldNames.includes("nodes")) {
195
+ query.hasPageInfo = true;
196
+ }
193
197
  selections.forEach((s) => {
194
198
  if (s.kind === "FragmentSpread") {
195
199
  query.fragments?.push(s.name.value.trim());
@@ -254,6 +258,20 @@ async function prepareContext(ctx) {
254
258
  const mutationFnName = (fn) => `useMutation${upperFirst(fn)}`;
255
259
  const formatNodes = (nodes) => nodes?.map((n) => `'${n}'`).join(",") ?? "";
256
260
  const getFragmentType = (q) => {
261
+ if (q.hasPageInfo) {
262
+ if (q.hasInlineFields || !q.fragments?.length) {
263
+ if (q.nodes?.length) {
264
+ let typePath = `${q.name}RootQuery`;
265
+ for (const node of q.nodes) {
266
+ typePath = `NonNullable<${typePath}>['${node}']`;
267
+ }
268
+ typePath = `NonNullable<${typePath}>['nodes'][number]`;
269
+ return typePath;
270
+ }
271
+ return `${q.name}RootQuery`;
272
+ }
273
+ return q.fragments.map((f) => `WithImagePath<${f}Fragment>`).join(" | ");
274
+ }
257
275
  if (q.hasInlineFields || !q.fragments?.length) {
258
276
  if (q.nodes?.length) {
259
277
  let typePath = `${q.name}RootQuery`;
@@ -272,6 +290,12 @@ async function prepareContext(ctx) {
272
290
  };
273
291
  const queryFnExp = (q, typed = false) => {
274
292
  const functionName = fnName(q.name);
293
+ if (q.hasPageInfo) {
294
+ if (!typed) {
295
+ return `export const ${functionName} = (params, options) => useWPConnection('${q.name}', [${formatNodes(q.nodes)}], false, params, options)`;
296
+ }
297
+ return ` export const ${functionName}: (params?: MaybeRefOrGetter<${q.name}QueryVariables>, options?: WPContentOptions) => WPConnectionResult<${getFragmentType(q)}>`;
298
+ }
275
299
  if (!typed) {
276
300
  return `export const ${functionName} = (params, options) => useWPContent('${q.name}', [${formatNodes(q.nodes)}], false, params, options)`;
277
301
  }
@@ -287,9 +311,14 @@ async function prepareContext(ctx) {
287
311
  ctx.generateImports = () => {
288
312
  const lines = [];
289
313
  const imports = [];
290
- if (queries.length > 0) {
314
+ const hasConnectionQueries = queries.some((q) => q.hasPageInfo);
315
+ const hasContentQueries = queries.some((q) => !q.hasPageInfo);
316
+ if (hasContentQueries) {
291
317
  imports.push("useWPContent");
292
318
  }
319
+ if (hasConnectionQueries) {
320
+ imports.push("useWPConnection");
321
+ }
293
322
  if (mutations.length > 0) {
294
323
  imports.push("useGraphqlMutation");
295
324
  }
@@ -367,6 +396,25 @@ async function prepareContext(ctx) {
367
396
  " status: Ref<AsyncDataRequestStatus>",
368
397
  "}",
369
398
  "",
399
+ "interface WPConnectionResult<T> {",
400
+ " data: ComputedRef<T[] | undefined>",
401
+ " pageInfo: ComputedRef<WPPageInfo | undefined>",
402
+ " loadMore: () => Promise<void>",
403
+ " pending: Ref<boolean>",
404
+ " refresh: () => Promise<void>",
405
+ " execute: () => Promise<void>",
406
+ " clear: () => void",
407
+ " error: Ref<Error | undefined>",
408
+ " status: Ref<AsyncDataRequestStatus>",
409
+ "}",
410
+ "",
411
+ "interface WPPageInfo {",
412
+ " hasNextPage: boolean",
413
+ " hasPreviousPage: boolean",
414
+ " startCursor?: string | null",
415
+ " endCursor?: string | null",
416
+ "}",
417
+ "",
370
418
  "type WPMutationResult<T> = GraphqlResponse<T>",
371
419
  "",
372
420
  "/** Adds relativePath to featuredImage.node when present (injected at runtime by transformData) */",
@@ -945,6 +993,7 @@ const module$1 = defineNuxtModule({
945
993
  configureVercelSettings(nuxt, logger);
946
994
  addImports([
947
995
  { name: "useWPContent", as: "useWPContent", from: resolver.resolve("./runtime/composables/useWPContent") },
996
+ { name: "useWPConnection", as: "useWPConnection", from: resolver.resolve("./runtime/composables/useWPConnection") },
948
997
  { name: "getRelativeImagePath", as: "getRelativeImagePath", from: resolver.resolve("./runtime/util/images") },
949
998
  { name: "isInternalLink", as: "isInternalLink", from: resolver.resolve("./runtime/util/links") },
950
999
  { name: "toRelativePath", as: "toRelativePath", from: resolver.resolve("./runtime/util/links") },
File without changes
@@ -0,0 +1,68 @@
1
+ import { useWPContent } from "./useWPContent.js";
2
+ import { computed, ref, toValue, watch as vueWatch } from "#imports";
3
+ export const useWPConnection = (queryName, connectionPath, fixImagePaths, params, options) => {
4
+ const loadMoreCursor = ref(null);
5
+ const isLoadingMore = ref(false);
6
+ const accumulatedItems = ref([]);
7
+ const mergedParams = computed(() => {
8
+ const userParams = toValue(params) ?? {};
9
+ if (loadMoreCursor.value) {
10
+ return { ...userParams, after: loadMoreCursor.value };
11
+ }
12
+ return userParams;
13
+ });
14
+ const result = useWPContent(queryName, connectionPath, fixImagePaths, mergedParams, options);
15
+ const currentNodes = computed(() => {
16
+ const connection = result.data.value;
17
+ if (!connection || typeof connection !== "object") return void 0;
18
+ const nodes = connection.nodes;
19
+ return Array.isArray(nodes) ? nodes : void 0;
20
+ });
21
+ const pageInfo = computed(() => {
22
+ const connection = result.data.value;
23
+ if (!connection || typeof connection !== "object") return void 0;
24
+ return connection.pageInfo;
25
+ });
26
+ vueWatch(currentNodes, (newNodes) => {
27
+ if (!newNodes?.length) return;
28
+ if (isLoadingMore.value) {
29
+ accumulatedItems.value = [...accumulatedItems.value, ...newNodes];
30
+ isLoadingMore.value = false;
31
+ } else {
32
+ accumulatedItems.value = [...newNodes];
33
+ loadMoreCursor.value = null;
34
+ }
35
+ }, { immediate: true });
36
+ const connectionData = computed(() => {
37
+ return accumulatedItems.value.length > 0 ? accumulatedItems.value : currentNodes.value;
38
+ });
39
+ async function loadMore() {
40
+ if (!pageInfo.value?.hasNextPage || !pageInfo.value.endCursor) return;
41
+ isLoadingMore.value = true;
42
+ loadMoreCursor.value = pageInfo.value.endCursor;
43
+ }
44
+ const returnValue = {
45
+ data: connectionData,
46
+ pageInfo,
47
+ loadMore,
48
+ pending: result.pending,
49
+ refresh: async () => {
50
+ accumulatedItems.value = [];
51
+ loadMoreCursor.value = null;
52
+ isLoadingMore.value = false;
53
+ await result.refresh();
54
+ },
55
+ execute: result.execute,
56
+ clear: result.clear,
57
+ error: result.error,
58
+ status: result.status,
59
+ transformError: result.transformError,
60
+ retryCount: result.retryCount,
61
+ isRetrying: result.isRetrying
62
+ };
63
+ const thenable = result;
64
+ return Object.assign(
65
+ thenable.then(() => returnValue),
66
+ returnValue
67
+ );
68
+ };
@@ -40,8 +40,12 @@ export const useWPContent = (queryName, nodes, fixImagePaths, params, options) =
40
40
  }, timeoutMs);
41
41
  }
42
42
  const getCachedDataFn = userGetCachedData ?? (clientCache === false ? noCacheGetCachedData : defaultGetCachedData);
43
+ const watchSources = restOptions.watch;
44
+ const autoWatch = isReactiveParams ? [...watchSources ?? [], resolvedParams] : watchSources;
43
45
  const asyncDataOptions = {
44
46
  ...restOptions,
47
+ // Watch reactive params to auto-refetch
48
+ ...autoWatch?.length && { watch: autoWatch },
45
49
  // Our getCachedData that properly checks static.data for SSG
46
50
  getCachedData: getCachedDataFn,
47
51
  // Enable graphql caching so the LRU cache is populated for subsequent navigations
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wpnuxt/core",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Nuxt module for WordPress integration via GraphQL (WPGraphQL)",
5
5
  "keywords": [
6
6
  "nuxt",