From 30c7b8b0b507213784fc3ac289d3a1c37f8c35b7 Mon Sep 17 00:00:00 2001 From: Pascal Martineau Date: Thu, 26 Mar 2026 15:32:13 -0400 Subject: [PATCH] feat: Attach the Authorization header if a wpAuthToken is present in the context --- wp-content/themes/headless/nuxt.config.ts | 10 +- wp-content/themes/headless/package.json | 4 +- wp-content/themes/headless/pnpm-lock.yaml | 96 ++++++++++++++----- .../themes/headless/server/graphql/context.ts | 3 +- .../headless/server/graphql/wp-hooks.ts | 12 +++ .../themes/headless/server/utils/auth.ts | 25 +++++ 6 files changed, 124 insertions(+), 26 deletions(-) create mode 100644 wp-content/themes/headless/server/graphql/wp-hooks.ts diff --git a/wp-content/themes/headless/nuxt.config.ts b/wp-content/themes/headless/nuxt.config.ts index ff73c8b..d57adad 100644 --- a/wp-content/themes/headless/nuxt.config.ts +++ b/wp-content/themes/headless/nuxt.config.ts @@ -36,7 +36,13 @@ export default defineNuxtConfig({ }, server: { context: ["server/graphql/context.ts"], - schema: [{ type: "remote", endpoint: `${process.env.NUXT_WP_URL}/graphql` }], + schema: [ + { + type: "remote", + endpoint: `${process.env.NUXT_WP_URL}/graphql`, + hooks: ["server/graphql/wp-hooks.ts"], + }, + ], }, }, @@ -48,7 +54,7 @@ export default defineNuxtConfig({ vite: { optimizeDeps: { - include: ["@vue/devtools-core", "@vue/devtools-kit", "zod", "es-toolkit/promise"], + include: ["@vue/devtools-core", "@vue/devtools-kit", "es-toolkit/promise", "zod"], }, }, }); diff --git a/wp-content/themes/headless/package.json b/wp-content/themes/headless/package.json index 9c5f69e..b242aa7 100644 --- a/wp-content/themes/headless/package.json +++ b/wp-content/themes/headless/package.json @@ -19,10 +19,12 @@ "dependencies": { "@iconify-json/cib": "^1.2.3", "@iconify-json/lucide": "^1.2.99", - "@lewebsimple/nuxt-graphql": "^0.7.5", + "@lewebsimple/nuxt-graphql": "^0.7.6", "@nuxt/ui": "^4.6.0", "@nuxtjs/seo": "^4.0.2", + "defu": "^6.1.4", "es-toolkit": "^1.45.1", + "jwt-decode": "^4.0.0", "nuxt": "^4.4.2", "nuxt-auth-utils": "^0.5.29", "nuxt-svgo": "^4.2.6", diff --git a/wp-content/themes/headless/pnpm-lock.yaml b/wp-content/themes/headless/pnpm-lock.yaml index cfdc712..f6fae9b 100644 --- a/wp-content/themes/headless/pnpm-lock.yaml +++ b/wp-content/themes/headless/pnpm-lock.yaml @@ -15,17 +15,23 @@ importers: specifier: ^1.2.99 version: 1.2.99 '@lewebsimple/nuxt-graphql': - specifier: ^0.7.5 - version: 0.7.5(graphql@16.13.1)(magicast@0.5.2)(zod@4.3.6) + specifier: ^0.7.6 + version: 0.7.6(graphql@16.13.1)(magicast@0.5.2)(zod@4.3.6) '@nuxt/ui': specifier: ^4.6.0 - version: 4.6.0(@tiptap/extensions@3.20.5(@tiptap/core@3.20.5(@tiptap/pm@3.20.5))(@tiptap/pm@3.20.5))(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.7)(y-protocols@1.0.7(yjs@13.6.30))(yjs@13.6.30))(db0@0.3.4)(embla-carousel@8.6.0)(ioredis@5.10.1)(magicast@0.5.2)(tailwindcss@4.2.2)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue-router@4.6.4(vue@3.5.31(typescript@5.9.3)))(vue@3.5.31(typescript@5.9.3))(yjs@13.6.30)(zod@4.3.6) + version: 4.6.0(@tiptap/extensions@3.20.5(@tiptap/core@3.20.5(@tiptap/pm@3.20.5))(@tiptap/pm@3.20.5))(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.7)(y-protocols@1.0.7(yjs@13.6.30))(yjs@13.6.30))(db0@0.3.4)(embla-carousel@8.6.0)(ioredis@5.10.1)(jwt-decode@4.0.0)(magicast@0.5.2)(tailwindcss@4.2.2)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue-router@4.6.4(vue@3.5.31(typescript@5.9.3)))(vue@3.5.31(typescript@5.9.3))(yjs@13.6.30)(zod@4.3.6) '@nuxtjs/seo': specifier: ^4.0.2 - version: 4.0.2(489f84e1ce5b91b262b98d380824761d) + version: 4.0.2(31740990aadd2f011fff9e543efaeeb0) + defu: + specifier: ^6.1.4 + version: 6.1.4 es-toolkit: specifier: ^1.45.1 version: 1.45.1 + jwt-decode: + specifier: ^4.0.0 + version: 4.0.0 nuxt: specifier: ^4.4.2 version: 4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@25.5.0)(@vue/compiler-sfc@3.5.31)(cac@6.7.14)(db0@0.3.4)(ioredis@5.10.1)(lightningcss@1.32.0)(magicast@0.5.2)(oxlint@1.57.0)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(terser@5.46.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.3) @@ -721,8 +727,8 @@ packages: graphql: ^16.13.1 zod: ^4.3.6 - '@lewebsimple/nuxt-graphql@0.7.5': - resolution: {integrity: sha512-W5QNyC+Vejw0H9+PG6r2+F2gx0TnFl0oLPIE+OuhBcYggzHp+z78kEMlbDyxZy2n0jJPG6TE0rmspoiRpTTMPQ==} + '@lewebsimple/nuxt-graphql@0.7.6': + resolution: {integrity: sha512-H4qH5T3zYmeqvrEnR32h7c5vhNBA9ztS/QDCipcjuqdplCIP+3VMxDrK/a7VwE8W1qiFYaechJBDeDI4oA7WVg==} peerDependencies: graphql: ^16 zod: ^4 @@ -3883,6 +3889,10 @@ packages: engines: {node: '>=6'} hasBin: true + jwt-decode@4.0.0: + resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==} + engines: {node: '>=18'} + kleur@4.1.5: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} @@ -4276,8 +4286,8 @@ packages: nuxt-link-checker@4.3.9: resolution: {integrity: sha512-iYJU+A/xUhk62v4tol9cdjJS1+ZOSl0+tdUObgifdeSts6IqAUByUAiX4H6yOY2tdQYKjahMFbQr1GJ+/4LYnQ==} - nuxt-og-image@6.2.5: - resolution: {integrity: sha512-ytmU/1b84/n3LwW3WeUwQHa2BncsuzjT5shTq3hKq8K/d+c8775/dXkOE5KB/W4eaZFeP6ShQoMf9S+ZIGjcpA==} + nuxt-og-image@6.2.6: + resolution: {integrity: sha512-kCmrXQvMwXGaSLo4uaF8FSIolhZq09Y+rfQwhT81WWOjIywPRJlNbVShYAGB7UayAKlQR0vXniAOGX331DJDgw==} engines: {node: '>=18.0.0'} hasBin: true peerDependencies: @@ -4372,8 +4382,8 @@ packages: '@types/node': optional: true - nuxtseo-layer-devtools@0.5.1: - resolution: {integrity: sha512-kBbQzZdQI95e6NFzhCgNSiRz+QAwZfv7oOuIHIHDeW0hoJoHBs71TbHwi8DIe23t5IcZ9lzxiG7qJsM+uPhiHg==} + nuxtseo-layer-devtools@5.0.2: + resolution: {integrity: sha512-iG+WCrVFzVp9F7Fe0Uz8eHtGmiJDXOMuWR5dCe9iCbf83/g3shpbEVcrRjA0NOTr1MG+MD8aWLZ0lb2+npkhXA==} nuxtseo-shared@0.9.0: resolution: {integrity: sha512-3V/vT2F4jON8mRThHPWzwVq6ZTU/J4PsqKwuaoON6b2OraULUhqOl1dOUQcduGHNgfYKhg9UygrT0xk+aUwM/g==} @@ -4389,6 +4399,20 @@ packages: zod: optional: true + nuxtseo-shared@5.0.2: + resolution: {integrity: sha512-rfF8JOAAYpudUBKgr2HABazxIcJycKl3KeON3ZD3ZsMLiVGq2+d3ZdGefyFgCcwytgbPR1ao+a65wjxzfdG7zw==} + peerDependencies: + '@nuxt/schema': ^3.16.0 || ^4.0.0 + nuxt: ^3.16.0 || ^4.0.0 + nuxt-site-config: ^3.2.0 || ^4.0.0 + vue: ^3.5.0 + zod: ^3.23.0 || ^4.0.0 + peerDependenciesMeta: + nuxt-site-config: + optional: true + zod: + optional: true + nypm@0.6.5: resolution: {integrity: sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==} engines: {node: '>=18'} @@ -6518,7 +6542,7 @@ snapshots: transitivePeerDependencies: - graphql-sock - '@lewebsimple/nuxt-graphql@0.7.5(graphql@16.13.1)(magicast@0.5.2)(zod@4.3.6)': + '@lewebsimple/nuxt-graphql@0.7.6(graphql@16.13.1)(magicast@0.5.2)(zod@4.3.6)': dependencies: '@graphql-codegen/core': 5.0.1(graphql@16.13.1) '@graphql-codegen/typed-document-node': 6.1.6(graphql@16.13.1) @@ -6885,7 +6909,7 @@ snapshots: rc9: 3.0.0 std-env: 3.10.0 - '@nuxt/ui@4.6.0(@tiptap/extensions@3.20.5(@tiptap/core@3.20.5(@tiptap/pm@3.20.5))(@tiptap/pm@3.20.5))(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.7)(y-protocols@1.0.7(yjs@13.6.30))(yjs@13.6.30))(db0@0.3.4)(embla-carousel@8.6.0)(ioredis@5.10.1)(magicast@0.5.2)(tailwindcss@4.2.2)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue-router@4.6.4(vue@3.5.31(typescript@5.9.3)))(vue@3.5.31(typescript@5.9.3))(yjs@13.6.30)(zod@4.3.6)': + '@nuxt/ui@4.6.0(@tiptap/extensions@3.20.5(@tiptap/core@3.20.5(@tiptap/pm@3.20.5))(@tiptap/pm@3.20.5))(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.7)(y-protocols@1.0.7(yjs@13.6.30))(yjs@13.6.30))(db0@0.3.4)(embla-carousel@8.6.0)(ioredis@5.10.1)(jwt-decode@4.0.0)(magicast@0.5.2)(tailwindcss@4.2.2)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue-router@4.6.4(vue@3.5.31(typescript@5.9.3)))(vue@3.5.31(typescript@5.9.3))(yjs@13.6.30)(zod@4.3.6)': dependencies: '@floating-ui/dom': 1.7.6 '@iconify/vue': 5.0.0(vue@3.5.31(typescript@5.9.3)) @@ -6920,7 +6944,7 @@ snapshots: '@tiptap/vue-3': 3.20.5(@floating-ui/dom@1.7.6)(@tiptap/core@3.20.5(@tiptap/pm@3.20.5))(@tiptap/pm@3.20.5)(vue@3.5.31(typescript@5.9.3)) '@unhead/vue': 2.1.12(vue@3.5.31(typescript@5.9.3)) '@vueuse/core': 14.2.1(vue@3.5.31(typescript@5.9.3)) - '@vueuse/integrations': 14.2.1(fuse.js@7.1.0)(vue@3.5.31(typescript@5.9.3)) + '@vueuse/integrations': 14.2.1(fuse.js@7.1.0)(jwt-decode@4.0.0)(vue@3.5.31(typescript@5.9.3)) '@vueuse/shared': 14.2.1(vue@3.5.31(typescript@5.9.3)) colortranslator: 5.0.0 consola: 3.4.2 @@ -7088,14 +7112,14 @@ snapshots: - vite - vue - '@nuxtjs/seo@4.0.2(489f84e1ce5b91b262b98d380824761d)': + '@nuxtjs/seo@4.0.2(31740990aadd2f011fff9e543efaeeb0)': dependencies: '@nuxt/kit': 4.4.2(magicast@0.5.2) '@nuxtjs/robots': 5.7.1(magicast@0.5.2)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue@3.5.31(typescript@5.9.3))(zod@4.3.6) '@nuxtjs/sitemap': 7.6.0(magicast@0.5.2)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue@3.5.31(typescript@5.9.3))(zod@4.3.6) nuxt: 4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@25.5.0)(@vue/compiler-sfc@3.5.31)(cac@6.7.14)(db0@0.3.4)(ioredis@5.10.1)(lightningcss@1.32.0)(magicast@0.5.2)(oxlint@1.57.0)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(terser@5.46.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.3) nuxt-link-checker: 4.3.9(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.2)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue@3.5.31(typescript@5.9.3)) - nuxt-og-image: 6.2.5(c0a0e494dd1f6d3e66ef78ce7a93ecda) + nuxt-og-image: 6.2.6(e4d8b77ed5b734d08cae157c5f939771) nuxt-schema-org: 5.0.10(@unhead/vue@2.1.12(vue@3.5.31(typescript@5.9.3)))(magicast@0.5.2)(unhead@2.1.12)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue@3.5.31(typescript@5.9.3))(zod@4.3.6) nuxt-seo-utils: 7.0.19(magicast@0.5.2)(rollup@4.60.0)(unhead@2.1.12)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue@3.5.31(typescript@5.9.3)) nuxt-site-config: 3.2.21(magicast@0.5.2)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue@3.5.31(typescript@5.9.3)) @@ -8497,13 +8521,14 @@ snapshots: '@vueuse/shared': 14.2.1(vue@3.5.31(typescript@5.9.3)) vue: 3.5.31(typescript@5.9.3) - '@vueuse/integrations@14.2.1(fuse.js@7.1.0)(vue@3.5.31(typescript@5.9.3))': + '@vueuse/integrations@14.2.1(fuse.js@7.1.0)(jwt-decode@4.0.0)(vue@3.5.31(typescript@5.9.3))': dependencies: '@vueuse/core': 14.2.1(vue@3.5.31(typescript@5.9.3)) '@vueuse/shared': 14.2.1(vue@3.5.31(typescript@5.9.3)) vue: 3.5.31(typescript@5.9.3) optionalDependencies: fuse.js: 7.1.0 + jwt-decode: 4.0.0 '@vueuse/metadata@10.11.1': {} @@ -9713,6 +9738,8 @@ snapshots: json5@2.2.3: {} + jwt-decode@4.0.0: {} + kleur@4.1.5: {} klona@2.0.6: {} @@ -10222,7 +10249,7 @@ snapshots: - vite - vue - nuxt-og-image@6.2.5(c0a0e494dd1f6d3e66ef78ce7a93ecda): + nuxt-og-image@6.2.6(e4d8b77ed5b734d08cae157c5f939771): dependencies: '@clack/prompts': 1.1.0 '@nuxt/devtools-kit': 3.2.4(magicast@0.5.2)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) @@ -10240,8 +10267,8 @@ snapshots: magicast: 0.5.2 mocked-exports: 0.1.1 nuxt-site-config: 4.0.7(@nuxt/schema@4.4.2)(magicast@0.5.2)(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@25.5.0)(@vue/compiler-sfc@3.5.31)(cac@6.7.14)(db0@0.3.4)(ioredis@5.10.1)(lightningcss@1.32.0)(magicast@0.5.2)(oxlint@1.57.0)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(terser@5.46.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.3))(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue@3.5.31(typescript@5.9.3))(zod@4.3.6) - nuxtseo-layer-devtools: 0.5.1(18fb9e32ac8899e4a09f8a1dd18f0dfd) - nuxtseo-shared: 0.9.0(adf425b2f21b31733a21c9a7846ef966) + nuxtseo-layer-devtools: 5.0.2(e7cd62de8d5c5d5de912549341a68f6a) + nuxtseo-shared: 5.0.2(adf425b2f21b31733a21c9a7846ef966) nypm: 0.6.5 ofetch: 1.5.1 ohash: 2.0.11 @@ -10554,15 +10581,15 @@ snapshots: - xml2js - yaml - nuxtseo-layer-devtools@0.5.1(18fb9e32ac8899e4a09f8a1dd18f0dfd): + nuxtseo-layer-devtools@5.0.2(e7cd62de8d5c5d5de912549341a68f6a): dependencies: '@nuxt/devtools-kit': 4.0.0-alpha.3(magicast@0.5.2)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) '@nuxt/kit': 4.4.2(magicast@0.5.2) - '@nuxt/ui': 4.6.0(@tiptap/extensions@3.20.5(@tiptap/core@3.20.5(@tiptap/pm@3.20.5))(@tiptap/pm@3.20.5))(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.7)(y-protocols@1.0.7(yjs@13.6.30))(yjs@13.6.30))(db0@0.3.4)(embla-carousel@8.6.0)(ioredis@5.10.1)(magicast@0.5.2)(tailwindcss@4.2.2)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue-router@4.6.4(vue@3.5.31(typescript@5.9.3)))(vue@3.5.31(typescript@5.9.3))(yjs@13.6.30)(zod@4.3.6) + '@nuxt/ui': 4.6.0(@tiptap/extensions@3.20.5(@tiptap/core@3.20.5(@tiptap/pm@3.20.5))(@tiptap/pm@3.20.5))(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.7)(y-protocols@1.0.7(yjs@13.6.30))(yjs@13.6.30))(db0@0.3.4)(embla-carousel@8.6.0)(ioredis@5.10.1)(jwt-decode@4.0.0)(magicast@0.5.2)(tailwindcss@4.2.2)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue-router@4.6.4(vue@3.5.31(typescript@5.9.3)))(vue@3.5.31(typescript@5.9.3))(yjs@13.6.30)(zod@4.3.6) '@shikijs/langs': 4.0.2 '@shikijs/themes': 4.0.2 '@vueuse/nuxt': 14.2.1(magicast@0.5.2)(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@25.5.0)(@vue/compiler-sfc@3.5.31)(cac@6.7.14)(db0@0.3.4)(ioredis@5.10.1)(lightningcss@1.32.0)(magicast@0.5.2)(oxlint@1.57.0)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(terser@5.46.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.3))(vue@3.5.31(typescript@5.9.3)) - nuxtseo-shared: 0.9.0(adf425b2f21b31733a21c9a7846ef966) + nuxtseo-shared: 5.0.2(adf425b2f21b31733a21c9a7846ef966) ofetch: 1.5.1 shiki: 4.0.2 ufo: 1.6.3 @@ -10646,6 +10673,31 @@ snapshots: - magicast - vite + nuxtseo-shared@5.0.2(adf425b2f21b31733a21c9a7846ef966): + dependencies: + '@clack/prompts': 1.1.0 + '@nuxt/devtools-kit': 4.0.0-alpha.3(magicast@0.5.2)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) + '@nuxt/kit': 4.4.2(magicast@0.5.2) + '@nuxt/schema': 4.4.2 + birpc: 4.0.0 + consola: 3.4.2 + defu: 6.1.4 + nuxt: 4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@25.5.0)(@vue/compiler-sfc@3.5.31)(cac@6.7.14)(db0@0.3.4)(ioredis@5.10.1)(lightningcss@1.32.0)(magicast@0.5.2)(oxlint@1.57.0)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(terser@5.46.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.3) + ofetch: 1.5.1 + pathe: 2.0.3 + pkg-types: 2.3.0 + radix3: 1.1.2 + sirv: 3.0.2 + std-env: 4.0.0 + ufo: 1.6.3 + vue: 3.5.31(typescript@5.9.3) + optionalDependencies: + nuxt-site-config: 4.0.7(@nuxt/schema@4.4.2)(magicast@0.5.2)(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@25.5.0)(@vue/compiler-sfc@3.5.31)(cac@6.7.14)(db0@0.3.4)(ioredis@5.10.1)(lightningcss@1.32.0)(magicast@0.5.2)(oxlint@1.57.0)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(terser@5.46.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.3))(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))(vue@3.5.31(typescript@5.9.3))(zod@4.3.6) + zod: 4.3.6 + transitivePeerDependencies: + - magicast + - vite + nypm@0.6.5: dependencies: citty: 0.2.1 diff --git a/wp-content/themes/headless/server/graphql/context.ts b/wp-content/themes/headless/server/graphql/context.ts index e0a2a84..fcee337 100644 --- a/wp-content/themes/headless/server/graphql/context.ts +++ b/wp-content/themes/headless/server/graphql/context.ts @@ -1,3 +1,4 @@ export default defineGraphQLContext(async (event) => { - return {}; + const wpAuthToken = await getAuthToken(event); + return { wpAuthToken }; }); diff --git a/wp-content/themes/headless/server/graphql/wp-hooks.ts b/wp-content/themes/headless/server/graphql/wp-hooks.ts new file mode 100644 index 0000000..66358c7 --- /dev/null +++ b/wp-content/themes/headless/server/graphql/wp-hooks.ts @@ -0,0 +1,12 @@ +import { defu } from "defu"; + +export default defineRemoteExecutorHooks({ + onRequest(request, context) { + // Attach the Authorization header if a wpAuthToken is present in the context + if (context?.wpAuthToken) { + request.extensions = defu(request.extensions, { + headers: { Authorization: `Bearer ${context.wpAuthToken}` }, + }); + } + }, +}); diff --git a/wp-content/themes/headless/server/utils/auth.ts b/wp-content/themes/headless/server/utils/auth.ts index b71156a..f2fc56e 100644 --- a/wp-content/themes/headless/server/utils/auth.ts +++ b/wp-content/themes/headless/server/utils/auth.ts @@ -1,3 +1,5 @@ +import { jwtDecode } from "jwt-decode"; + import type { AuthPayloadFragment, AuthUserFragment } from "#graphql/types"; import type { H3Event } from "h3"; @@ -47,3 +49,26 @@ function getAuthUser(user: AuthUserFragment) { roles: user.roles.nodes.map(({ name }) => name) || [], }; } + +/** + * Retrieve the authentication token from the user's session, checking for expiration and handling token refresh if necessary. + * + * @param event The H3 event object, used to access the user's session data. + * @returns A promise that resolves to the authentication token if it is valid, or undefined if there is no valid token or if the user is not authenticated. + */ +export async function getAuthToken(event: H3Event) { + // Retrieve user session, return if none + const session = await getUserSession(event); + if (!session.secure) { + return; + } + + // Extract tokens and check expiration + const decoded = jwtDecode<{ exp: number }>(session.secure.authToken); + const isExpired = decoded.exp * 1000 < Date.now(); + if (isExpired) { + // TOOD: Refresh token logic + } + + return session.secure.authToken; +}