@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
package/dist/module.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { defu } from 'defu';
|
|
2
|
-
import { promises, cpSync, existsSync, statSync,
|
|
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
|
|
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
|
|
377
|
-
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",
|
|
@@ -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.
|
|
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.
|
|
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
|
|
68
|
+
"dev:prepare": "nuxt-module-build build --stub",
|
|
69
69
|
"lint": "eslint src",
|
|
70
70
|
"test": "vitest run",
|
|
71
71
|
"test:watch": "vitest watch",
|