Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,21 @@ export default defineNuxtModule<ModuleOptions>({
}, 5000);
}

if (!options.disableGraphql) {
// TODO: Remove when package fixed with valid ESM exports
nuxt.options.build.transpile.push(({ isServer }) => !isServer && 'gql-query-builder');
}

nuxt.options.build.transpile.push(({ isServer }) => !isServer && 'js-sha256');
// TODO: Remove when package fixed with valid ESM exports
// gql-query-builder (CJS) and js-sha256 (UMD) expose named exports that Vite 7 /
// Nuxt 4 cannot statically detect from the raw package output. They must NOT be
// added to build.transpile (which would serve them raw, breaking the named imports
// and the client bundle → no hydration). Instead they are pre-bundled via
// optimizeDeps so esbuild produces a proper interop wrapper, and the runtime reads
// the members through the runtime/helpers/*-interop.ts modules.
extendViteConfig((config) => {
config.optimizeDeps = config.optimizeDeps || {};
config.optimizeDeps.include = config.optimizeDeps.include || [];
config.optimizeDeps.exclude = config.optimizeDeps.exclude || [];
config.optimizeDeps.include.push('gql-query-builder');
// js-sha256 backs password hashing and is used regardless of GraphQL.
config.optimizeDeps.include.push('js-sha256');
// gql-query-builder is only reached through the GraphQL composables.
if (!options.disableGraphql) {
config.optimizeDeps.include.push('gql-query-builder');
}
});

nuxt.hook('nitro:config', (nitro) => {
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/composables/gql-async-query.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { query } from 'gql-query-builder';
import gql from 'graphql-tag';
import { type AsyncData, callWithNuxt, useAsyncData, useNuxtApp } from 'nuxt/app';

import type { IGraphQLOptions } from '../interfaces/graphql-options.interface';

import { hashPasswords } from '../functions/graphql-meta';
import { query } from '../helpers/gql-query-builder-interop';
import { useAuthState } from '../states/auth';
import { useAuth } from './use-auth';
import { useHelper } from './use-helper';
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/composables/gql-mutation.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { mutation } from 'gql-query-builder';
import gql from 'graphql-tag';
import { callWithNuxt, useNuxtApp } from 'nuxt/app';

import type { GraphqlError } from '../interfaces/graphql-error.interface';
import type { IGraphQLOptions } from '../interfaces/graphql-options.interface';

import { hashPasswords } from '../functions/graphql-meta';
import { mutation } from '../helpers/gql-query-builder-interop';
import { useAuthState } from '../states/auth';
import { useAuth } from './use-auth';
import { useRequestOptions } from './use-request-options';
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/composables/gql-query.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { query } from 'gql-query-builder';
import gql from 'graphql-tag';
import { callWithNuxt, useNuxtApp } from 'nuxt/app';

import type { GraphqlError } from '../interfaces/graphql-error.interface';
import type { IGraphQLOptions } from '../interfaces/graphql-options.interface';

import { hashPasswords } from '../functions/graphql-meta';
import { query } from '../helpers/gql-query-builder-interop';
import { useAuthState } from '../states/auth';
import { useAuth } from './use-auth';
import { useRequestOptions } from './use-request-options';
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/composables/gql-subscription.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { Client } from 'graphql-ws';

import { subscription } from 'gql-query-builder';
import gql from 'graphql-tag';
import { useNuxtApp } from 'nuxt/app';
import { ref } from 'vue';
Expand All @@ -9,6 +8,7 @@ import type { IGraphQLOptions } from '../interfaces/graphql-options.interface';
import type { ReturnTypeOfSubscription } from '../interfaces/return-type-of-subscription.interface';

import { hashPasswords } from '../functions/graphql-meta';
import { subscription } from '../helpers/gql-query-builder-interop';

export async function gqlSubscription<T = any>(method: string, options: IGraphQLOptions = {}): Promise<ReturnTypeOfSubscription<T>> {
const { _meta, _wsClient } = useNuxtApp();
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/functions/graphql-meta.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { buildClientSchema, getIntrospectionQuery } from 'graphql';
import { sha256 } from 'js-sha256';
import { ofetch } from 'ofetch';

import type { GraphQLMeta } from '../../generate';

import { useGraphQLMeta } from '../composables/use-graphql-meta';
import { sha256 } from '../helpers/js-sha256-interop';

/**
* Hash a string with SHA-256
Expand Down
26 changes: 26 additions & 0 deletions src/runtime/helpers/gql-query-builder-interop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Interop layer for gql-query-builder (CJS with __esModule, no ESM entry point).
//
// `gql-query-builder` exposes `query`/`mutation`/`subscription` as named exports
// that Vite 7 / Nuxt 4 cannot statically detect from the raw CJS output, so a
// direct `import { query } from 'gql-query-builder'` breaks the client bundle
// (no hydration). Importing the whole namespace and resolving the members at
// runtime works for both CJS shapes:
// - __esModule (exports.query = ...) → member sits directly on the namespace
// - module.exports = {...} → member sits under `.default`
// The package must stay out of `build.transpile` and be pre-bundled via
// optimizeDeps (dev) / handled by the commonjs plugin (build) for the interop
// wrapper to be produced (see module.ts).
//
// This file deliberately lives outside the auto-imported runtime dirs so its
// generic `query`/`mutation`/`subscription` exports are NOT registered as global
// Nuxt auto-imports. It is kept separate from the js-sha256 interop so the
// disableGraphql / password-hashing path never pulls gql-query-builder into the
// module graph.

import * as gqlQueryBuilder from 'gql-query-builder';

const mod = (gqlQueryBuilder as any).query ? (gqlQueryBuilder as any) : ((gqlQueryBuilder as any).default ?? gqlQueryBuilder);

export const query: typeof import('gql-query-builder').query = mod.query;
export const mutation: typeof import('gql-query-builder').mutation = mod.mutation;
export const subscription: typeof import('gql-query-builder').subscription = mod.subscription;
20 changes: 20 additions & 0 deletions src/runtime/helpers/js-sha256-interop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Interop layer for js-sha256 (UMD/CJS, no ESM entry point).
//
// `js-sha256` exposes its members as named exports that Vite 7 / Nuxt 4 cannot
// statically detect from the raw UMD output, so a direct `import { sha256 } from
// 'js-sha256'` breaks the client bundle (no hydration). Importing the whole
// namespace and resolving the member at runtime works for both CJS shapes:
// - __esModule (exports.sha256 = ...) → member sits directly on the namespace
// - module.exports = {...} → member sits under `.default`
// The package must stay out of `build.transpile` and be pre-bundled via
// optimizeDeps (dev) / handled by the commonjs plugin (build) for the interop
// wrapper to be produced (see module.ts).
//
// This file deliberately lives outside the auto-imported runtime dirs so its
// generic `sha256` export is NOT registered as a global Nuxt auto-import.

import * as jsSha256 from 'js-sha256';

const mod = (jsSha256 as any).sha256 ? (jsSha256 as any) : ((jsSha256 as any).default ?? jsSha256);

export const sha256: typeof import('js-sha256').sha256 = mod.sha256;
Loading