@wpnuxt/core 2.0.0-alpha.1 → 2.0.0-alpha.2

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,7 +1,7 @@
1
1
  {
2
2
  "name": "wpnuxt",
3
3
  "configKey": "wpNuxt",
4
- "version": "2.0.0-alpha.0",
4
+ "version": "2.0.0-alpha.1",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -1,10 +1,11 @@
1
1
  import { defu } from 'defu';
2
- import { promises, cpSync, existsSync, statSync, mkdirSync, writeFileSync } from 'node:fs';
2
+ import { promises, cpSync, existsSync, statSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
3
3
  import { join } from 'node:path';
4
4
  import { useLogger, createResolver, resolveFiles, defineNuxtModule, addPlugin, addImports, addComponentsDir, addTemplate, addTypeTemplate, hasNuxtModule, installModule } from '@nuxt/kit';
5
5
  import { upperFirst } from 'scule';
6
6
  import { ref } from 'vue';
7
7
  import { parse, GraphQLError } from 'graphql';
8
+ import { execSync } from 'node:child_process';
8
9
 
9
10
  function randHashGenerator(length = 12) {
10
11
  return Math.random().toString(36).substring(2, 2 + length).toUpperCase().padEnd(length, "0");
@@ -234,6 +235,149 @@ async function prepareFunctions(ctx) {
234
235
  });
235
236
  }
236
237
 
238
+ async function validateWordPressEndpoint(wordpressUrl, graphqlEndpoint = "/graphql", options = {}) {
239
+ const fullUrl = `${wordpressUrl}${graphqlEndpoint}`;
240
+ try {
241
+ const controller = new AbortController();
242
+ const timeout = setTimeout(() => controller.abort(), 1e4);
243
+ const response = await fetch(fullUrl, {
244
+ method: "POST",
245
+ headers: {
246
+ "Content-Type": "application/json"
247
+ },
248
+ body: JSON.stringify({
249
+ query: "{ __typename }"
250
+ }),
251
+ signal: controller.signal
252
+ });
253
+ clearTimeout(timeout);
254
+ if (!response.ok) {
255
+ throw new Error(
256
+ `[WPNuxt] WordPress GraphQL endpoint returned HTTP ${response.status}.
257
+
258
+ URL: ${fullUrl}
259
+
260
+ Possible causes:
261
+ - The WordPress site is down or unreachable
262
+ - WPGraphQL plugin is not installed or activated
263
+ - The GraphQL endpoint path is incorrect (default: /graphql)
264
+
265
+ Check your wpNuxt.wordpressUrl configuration in nuxt.config.ts`
266
+ );
267
+ }
268
+ const data = await response.json();
269
+ if (!data || typeof data !== "object") {
270
+ throw new Error(
271
+ `[WPNuxt] WordPress GraphQL endpoint returned invalid response.
272
+
273
+ URL: ${fullUrl}
274
+
275
+ The endpoint did not return valid JSON. Make sure WPGraphQL plugin is installed and activated.`
276
+ );
277
+ }
278
+ if (data.errors && !data.data) {
279
+ const errorMessage = data.errors[0]?.message || "Unknown error";
280
+ throw new Error(
281
+ `[WPNuxt] WordPress GraphQL endpoint returned an error: ${errorMessage}
282
+
283
+ URL: ${fullUrl}
284
+
285
+ Make sure WPGraphQL plugin is installed and activated on your WordPress site.`
286
+ );
287
+ }
288
+ if (options.schemaPath && !existsSync(options.schemaPath)) {
289
+ try {
290
+ execSync(`npx get-graphql-schema "${fullUrl}" > "${options.schemaPath}"`, {
291
+ stdio: "pipe",
292
+ timeout: 6e4
293
+ // 60 second timeout
294
+ });
295
+ patchWPGraphQLSchema(options.schemaPath);
296
+ } catch (err) {
297
+ const error = err;
298
+ throw new Error(
299
+ `[WPNuxt] Failed to download GraphQL schema.
300
+
301
+ URL: ${fullUrl}
302
+ Error: ${error.stderr?.toString() || error.message}
303
+
304
+ Make sure WPGraphQL plugin is installed and activated on your WordPress site.`
305
+ );
306
+ }
307
+ }
308
+ } catch (error) {
309
+ if (error instanceof Error && error.message.startsWith("[WPNuxt]")) {
310
+ throw error;
311
+ }
312
+ const err = error;
313
+ const errorCode = err.code || err.cause?.code || "";
314
+ if (err.name === "AbortError") {
315
+ throw new Error(
316
+ `[WPNuxt] WordPress GraphQL endpoint timed out after 10 seconds.
317
+
318
+ URL: ${fullUrl}
319
+
320
+ The server did not respond in time. Check if the WordPress site is accessible.`
321
+ );
322
+ }
323
+ if (errorCode === "ENOTFOUND" || err.message?.includes("getaddrinfo")) {
324
+ throw new Error(
325
+ `[WPNuxt] WordPress site not found - DNS lookup failed.
326
+
327
+ URL: ${fullUrl}
328
+
329
+ The domain could not be resolved. Please check:
330
+ - The URL is spelled correctly (no typos)
331
+ - The domain exists and is properly configured
332
+ - Your network connection is working
333
+
334
+ Check your wpNuxt.wordpressUrl configuration in nuxt.config.ts`
335
+ );
336
+ }
337
+ if (errorCode === "ECONNREFUSED") {
338
+ throw new Error(
339
+ `[WPNuxt] Connection refused to WordPress site.
340
+
341
+ URL: ${fullUrl}
342
+
343
+ The server is not accepting connections. Check if the WordPress site is running.`
344
+ );
345
+ }
346
+ throw new Error(
347
+ `[WPNuxt] Failed to connect to WordPress GraphQL endpoint.
348
+
349
+ URL: ${fullUrl}
350
+ Error: ${err.message || "Unknown error"}
351
+
352
+ Check your wpNuxt.wordpressUrl configuration in nuxt.config.ts`
353
+ );
354
+ }
355
+ }
356
+ function patchWPGraphQLSchema(schemaPath) {
357
+ let schema = readFileSync(schemaPath, "utf-8");
358
+ const problematicInterfaces = [
359
+ "Connection",
360
+ "Edge",
361
+ "OneToOneConnection"
362
+ ];
363
+ problematicInterfaces.push("NodeWithEditorBlocks");
364
+ for (const iface of problematicInterfaces) {
365
+ schema = schema.replace(
366
+ new RegExp(`implements\\s+${iface}\\s*\\{`, "g"),
367
+ "{"
368
+ );
369
+ schema = schema.replace(
370
+ new RegExp(`implements\\s+${iface}\\s+&\\s+`, "g"),
371
+ "implements "
372
+ );
373
+ schema = schema.replace(
374
+ new RegExp(`\\s*&\\s*${iface}(?=\\s*[&{])`, "g"),
375
+ ""
376
+ );
377
+ }
378
+ writeFileSync(schemaPath, schema);
379
+ }
380
+
237
381
  const module$1 = defineNuxtModule({
238
382
  meta: {
239
383
  name: "wpnuxt",
@@ -267,6 +411,16 @@ const module$1 = defineNuxtModule({
267
411
  const mergedQueriesFolder = await mergeQueries(nuxt, wpNuxtConfig, resolver);
268
412
  setupServerOptions(nuxt, resolver, logger);
269
413
  setupClientOptions(nuxt, resolver, logger);
414
+ if (wpNuxtConfig.downloadSchema) {
415
+ const schemaPath = join(nuxt.options.rootDir, "schema.graphql");
416
+ logger.debug(`Validating WordPress endpoint: ${wpNuxtConfig.wordpressUrl}${wpNuxtConfig.graphqlEndpoint}`);
417
+ await validateWordPressEndpoint(
418
+ wpNuxtConfig.wordpressUrl,
419
+ wpNuxtConfig.graphqlEndpoint,
420
+ { schemaPath }
421
+ );
422
+ logger.debug("WordPress endpoint validation passed");
423
+ }
270
424
  await registerModules(nuxt, resolver, wpNuxtConfig, mergedQueriesFolder);
271
425
  nuxt.hook("devtools:customTabs", (tabs) => {
272
426
  const middlewareTab = tabs.find((tab) => tab.name === "nuxt-graphql-middleware");
@@ -333,9 +487,13 @@ function loadConfig(options, nuxt) {
333
487
  const config = defu({
334
488
  wordpressUrl: process.env.WPNUXT_WORDPRESS_URL,
335
489
  graphqlEndpoint: process.env.WPNUXT_GRAPHQL_ENDPOINT,
336
- downloadSchema: process.env.WPNUXT_DOWNLOAD_SCHEMA ? process.env.WPNUXT_DOWNLOAD_SCHEMA === "true" : void 0,
490
+ // Only override downloadSchema if env var is explicitly set
491
+ downloadSchema: process.env.WPNUXT_DOWNLOAD_SCHEMA !== void 0 ? process.env.WPNUXT_DOWNLOAD_SCHEMA === "true" : void 0,
337
492
  debug: process.env.WPNUXT_DEBUG ? process.env.WPNUXT_DEBUG === "true" : void 0
338
493
  }, options);
494
+ if (config.downloadSchema === void 0) {
495
+ config.downloadSchema = true;
496
+ }
339
497
  nuxt.options.runtimeConfig.public.wordpressUrl = config.wordpressUrl;
340
498
  nuxt.options.runtimeConfig.public.wpNuxt = {
341
499
  wordpressUrl: config.wordpressUrl,
@@ -355,7 +513,8 @@ function loadConfig(options, nuxt) {
355
513
  return config;
356
514
  }
357
515
  const SERVER_OPTIONS_TEMPLATE = `import { defineGraphqlServerOptions } from '@wpnuxt/core/server-options'
358
- import { getHeader } from 'h3'
516
+ import { getHeader, getCookie } from 'h3'
517
+ import { useRuntimeConfig } from '#imports'
359
518
 
360
519
  /**
361
520
  * WPNuxt default server options for nuxt-graphql-middleware.
@@ -363,18 +522,32 @@ import { getHeader } from 'h3'
363
522
  * This enables:
364
523
  * - Cookie forwarding for WordPress preview mode
365
524
  * - Authorization header forwarding for authenticated requests
525
+ * - Auth token from cookie for @wpnuxt/auth
366
526
  * - Consistent error logging
367
527
  *
368
528
  * Users can customize by creating their own server/graphqlMiddleware.serverOptions.ts
369
529
  */
370
530
  export default defineGraphqlServerOptions({
371
531
  async serverFetchOptions(event, _operation, _operationName, _context) {
532
+ // Get auth token from Authorization header or from cookie
533
+ let authorization = getHeader(event, 'authorization') || ''
534
+
535
+ // If no Authorization header, check for auth token in cookie (@wpnuxt/auth)
536
+ if (!authorization) {
537
+ const config = useRuntimeConfig().public.wpNuxtAuth as { cookieName?: string } | undefined
538
+ const cookieName = config?.cookieName || 'wpnuxt-auth-token'
539
+ const authToken = getCookie(event, cookieName)
540
+ if (authToken) {
541
+ authorization = \`Bearer \${authToken}\`
542
+ }
543
+ }
544
+
372
545
  return {
373
546
  headers: {
374
547
  // Forward WordPress auth cookies for previews
375
548
  Cookie: getHeader(event, 'cookie') || '',
376
- // Forward authorization header if present
377
- Authorization: getHeader(event, 'authorization') || ''
549
+ // Forward authorization header or token from cookie
550
+ Authorization: authorization
378
551
  }
379
552
  }
380
553
  },
@@ -471,7 +644,7 @@ async function registerModules(nuxt, resolver, wpNuxtConfig, mergedQueriesFolder
471
644
  graphqlEndpoint: `${wpNuxtConfig.wordpressUrl}${wpNuxtConfig.graphqlEndpoint}`,
472
645
  autoImportPatterns: [mergedQueriesFolder],
473
646
  includeComposables: true,
474
- downloadSchema: wpNuxtConfig.downloadSchema,
647
+ downloadSchema: wpNuxtConfig.downloadSchema ?? true,
475
648
  enableFileUploads: true,
476
649
  // Use WPNuxt-branded API route prefix
477
650
  serverApiPrefix: "/api/wpnuxt",
@@ -1,12 +1,12 @@
1
1
  query Viewer {
2
2
  viewer {
3
- username
4
- userId
5
3
  id
6
- email
7
- description
4
+ userId
5
+ username
8
6
  firstName
9
7
  lastName
8
+ name
9
+ description
10
10
  locale
11
11
  url
12
12
  uri
@@ -7,5 +7,4 @@ fragment GeneralSettings on GeneralSettings {
7
7
  startOfWeek
8
8
  timezone
9
9
  timeFormat
10
- email
11
10
  }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Type stubs for Nuxt-generated imports.
3
+ * These are used during module development when .nuxt folder doesn't exist.
4
+ * Actual types are generated at runtime in consuming applications.
5
+ */
6
+
7
+ /* eslint-disable @typescript-eslint/no-explicit-any */
8
+
9
+ // Stub for #imports
10
+ export const computed: any
11
+ export const useAsyncGraphqlQuery: any
12
+ export const useGraphqlState: any
13
+ export const useRuntimeConfig: any
14
+ export const useRoute: any
15
+
16
+ // Stub for #nuxt-graphql-middleware/operation-types
17
+ export type Query = Record<string, any>
18
+
19
+ // Stub for #build/graphql-operations
20
+ export type PostFragment = any
21
+ export type PageFragment = any
22
+ export type MenuItemFragment = any
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wpnuxt/core",
3
- "version": "2.0.0-alpha.1",
3
+ "version": "2.0.0-alpha.2",
4
4
  "description": "Nuxt module for WordPress integration via GraphQL (WPGraphQL)",
5
5
  "keywords": [
6
6
  "nuxt",
@@ -47,7 +47,7 @@
47
47
  "@radya/nuxt-dompurify": "^1.0.5",
48
48
  "defu": "^6.1.4",
49
49
  "graphql": "^16.12.0",
50
- "nuxt-graphql-middleware": "5.3.0",
50
+ "nuxt-graphql-middleware": "5.3.1",
51
51
  "scule": "^1.3.0"
52
52
  },
53
53
  "devDependencies": {
@@ -65,7 +65,7 @@
65
65
  },
66
66
  "scripts": {
67
67
  "build": "nuxt-module-build build",
68
- "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare",
68
+ "dev:prepare": "nuxt-module-build build --stub",
69
69
  "lint": "eslint src",
70
70
  "test": "vitest run",
71
71
  "test:watch": "vitest watch",