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
8 changes: 8 additions & 0 deletions docs/configuration/client-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ export default defineGraphqlClientOptions({})

:::

### Nuxt Layers

The client options file is also discovered from
[Nuxt layers](https://nuxt.com/docs/getting-started/layers). The module checks
all layers in order, starting with the main app. The first layer that contains a
`graphqlMiddleware.clientOptions` file wins — options from multiple layers are
**not** merged.

## Defining Client Context

Implement the `buildClientContext()` method to return an object with string
Expand Down
8 changes: 8 additions & 0 deletions docs/configuration/server-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ export default defineGraphqlServerOptions({

:::

### Nuxt Layers

The server options file is also discovered from
[Nuxt layers](https://nuxt.com/docs/getting-started/layers). The module checks
all layers in order, starting with the main app. The first layer that contains a
`graphqlMiddleware.serverOptions` file wins — options from multiple layers are
**not** merged.

## doGraphqlRequest

Provide a custom method that performs the request to the GraphQL server. It
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineGraphqlClientOptions } from './../../../../src/client-options'

export default defineGraphqlClientOptions({
buildClientContext() {
return {
fromLayer: 'true',
}
},
})
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
import { defineGraphqlServerOptions } from './../../../../src/server-options'

export default defineGraphqlServerOptions({})
export default defineGraphqlServerOptions({
serverFetchOptions: function (_event, _operation, operationName) {
const headers: Record<string, any> = {
'x-nuxt-header-server': 'Value from layer',
authentication: 'server-token',
'x-apollo-operation-name': operationName,
}
return { headers }
},
})
12 changes: 0 additions & 12 deletions playground-layers/server/graphqlMiddleware.serverOptions.ts

This file was deleted.

36 changes: 23 additions & 13 deletions src/build/ModuleHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,17 +228,32 @@ export class ModuleHelper {
}

/**
* Find the path to the graphqlMiddleware.serverOptions.ts file.
* Find a file across all Nuxt layers. The first layer (main app) takes
* precedence over extended layers.
*/
private findInLayers(
fileName: string,
getDir: (layer: (typeof this.nuxt.options._layers)[number]) => string,
): string | null {
for (const layer of this.nuxt.options._layers) {
const dir = getDir(layer)
const resolver = createResolver(dir)
const found = fileExists(resolver.resolve(fileName))
if (found) {
return found
}
}
return null
}

private findServerOptions(): string | null {
// Look for the file in the server directory.
const newPath = this.resolvers.server.resolve(
const found = this.findInLayers(
'graphqlMiddleware.serverOptions',
(layer) => layer.config.serverDir ?? layer.config.rootDir + '/server',
)
const serverPath = fileExists(newPath)

if (serverPath) {
return serverPath
if (found) {
return found
}

// Check for previous locations of the server options file that are not
Expand Down Expand Up @@ -268,15 +283,10 @@ export class ModuleHelper {
}

private findClientOptions(): string | null {
const clientOptionsPath = this.resolvers.app.resolve(
return this.findInLayers(
'graphqlMiddleware.clientOptions',
(layer) => layer.config.appDir ?? layer.config.srcDir,
)

if (fileExists(clientOptionsPath)) {
return clientOptionsPath
}

return null
}

/**
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/mcp/module-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ describe('MCP Module Config Tool', async () => {

expect(structured.paths).toMatchInlineSnapshot(`
{
"clientOptions": "./app/graphqlMiddleware.clientOptions",
"clientOptions": "./app/graphqlMiddleware.clientOptions.ts",
"documentTypes": ".nuxt/graphql-operations/index.d.ts",
"runtimeTypes": "../../../src/runtime/types.ts",
"schema": "../schema.graphql",
Expand Down
50 changes: 50 additions & 0 deletions test/layer-options.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { describe, expect, test } from 'vitest'
import { readFileSync } from 'fs'
import { join } from 'path'

const PLAYGROUND_LAYERS_DIR = join(
process.cwd(),
'playground-layers/.nuxt/nuxt-graphql-middleware',
)

const PLAYGROUND_DIR = join(
process.cwd(),
'playground/.nuxt/nuxt-graphql-middleware',
)

function readGenerated(dir: string, file: string): string {
return readFileSync(join(dir, file), 'utf-8')
}

/**
* @see https://github.com/dulnan/nuxt-graphql-middleware/issues/81
*/
describe('Layer options discovery', () => {
test('playground-layers: server options are found from the layer', () => {
const content = readGenerated(PLAYGROUND_LAYERS_DIR, 'server-options.js')
expect(content).toContain(
"import serverOptions from '../../layers/test-layer/server/graphqlMiddleware.serverOptions.ts'",
)
})

test('playground-layers: client options are found from the layer', () => {
const content = readGenerated(PLAYGROUND_LAYERS_DIR, 'client-options.js')
expect(content).toContain(
"import clientOptions from '../../layers/test-layer/app/graphqlMiddleware.clientOptions.ts'",
)
})

test('playground: server options are found from the main app (no layers involved)', () => {
const content = readGenerated(PLAYGROUND_DIR, 'server-options.js')
expect(content).toContain(
"import serverOptions from '../../server/graphqlMiddleware.serverOptions.ts'",
)
})

test('playground: client options are found from the main app', () => {
const content = readGenerated(PLAYGROUND_DIR, 'client-options.js')
expect(content).toContain(
"import clientOptions from '../../app/graphqlMiddleware.clientOptions",
)
})
})
22 changes: 6 additions & 16 deletions test/runtime/serverHandler/doGraphqlRequest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,11 @@ const graphqlEndpointCalls: Array<{
vi.mock('#nuxt-graphql-middleware/server-options', () => {
return {
serverOptions: {
serverFetchOptions: (
_event: any,
operation: any,
operationName: any,
) => {
serverFetchOptions: (_event: any, operation: any, operationName: any) => {
serverFetchOptionsCalls.push({ operation, operationName })
return {}
},
graphqlEndpoint: (
_event: any,
operation: any,
operationName: any,
) => {
graphqlEndpoint: (_event: any, operation: any, operationName: any) => {
graphqlEndpointCalls.push({ operation, operationName })
return 'http://localhost/graphql'
},
Expand Down Expand Up @@ -99,9 +91,8 @@ describe('doGraphqlRequest', () => {
serverFetchOptionsCalls.length = 0
graphqlEndpointCalls.length = 0

const { doGraphqlRequest } = await import(
'./../../../src/runtime/server/utils/doGraphqlRequest'
)
const { doGraphqlRequest } =
await import('./../../../src/runtime/server/utils/doGraphqlRequest')

await doGraphqlRequest(
{
Expand Down Expand Up @@ -129,9 +120,8 @@ describe('doGraphqlRequest', () => {
serverFetchOptionsCalls.length = 0
graphqlEndpointCalls.length = 0

const { doGraphqlRequest } = await import(
'./../../../src/runtime/server/utils/doGraphqlRequest'
)
const { doGraphqlRequest } =
await import('./../../../src/runtime/server/utils/doGraphqlRequest')

await doGraphqlRequest(
{
Expand Down
Loading