diff --git a/.changeset/@graphql-yoga_apollo-link-2266-dependencies.md b/.changeset/@graphql-yoga_apollo-link-2266-dependencies.md new file mode 100644 index 0000000000..b5e8a85224 --- /dev/null +++ b/.changeset/@graphql-yoga_apollo-link-2266-dependencies.md @@ -0,0 +1,5 @@ +--- +'@graphql-yoga/apollo-link': patch +--- +dependencies updates: + - Updated dependency [`@graphql-tools/executor-http@0.0.8` ↗︎](https://www.npmjs.com/package/@graphql-tools/executor-http/v/0.0.8) (from `0.0.7`, in `dependencies`) diff --git a/.changeset/@graphql-yoga_graphiql-2266-dependencies.md b/.changeset/@graphql-yoga_graphiql-2266-dependencies.md new file mode 100644 index 0000000000..faf62f68f1 --- /dev/null +++ b/.changeset/@graphql-yoga_graphiql-2266-dependencies.md @@ -0,0 +1,5 @@ +--- +'@graphql-yoga/graphiql': patch +--- +dependencies updates: + - Updated dependency [`@graphql-tools/url-loader@7.16.29` ↗︎](https://www.npmjs.com/package/@graphql-tools/url-loader/v/7.16.29) (from `7.16.28`, in `dependencies`) diff --git a/.changeset/@graphql-yoga_plugin-apollo-inline-trace-2266-dependencies.md b/.changeset/@graphql-yoga_plugin-apollo-inline-trace-2266-dependencies.md new file mode 100644 index 0000000000..bc90637fe2 --- /dev/null +++ b/.changeset/@graphql-yoga_plugin-apollo-inline-trace-2266-dependencies.md @@ -0,0 +1,5 @@ +--- +'@graphql-yoga/plugin-apollo-inline-trace': patch +--- +dependencies updates: + - Updated dependency [`@whatwg-node/fetch@^0.6.1` ↗︎](https://www.npmjs.com/package/@whatwg-node/fetch/v/0.6.1) (from `^0.5.1`, in `peerDependencies`) diff --git a/.changeset/@graphql-yoga_plugin-apq-2266-dependencies.md b/.changeset/@graphql-yoga_plugin-apq-2266-dependencies.md new file mode 100644 index 0000000000..9ec2d02521 --- /dev/null +++ b/.changeset/@graphql-yoga_plugin-apq-2266-dependencies.md @@ -0,0 +1,5 @@ +--- +'@graphql-yoga/plugin-apq': patch +--- +dependencies updates: + - Updated dependency [`@whatwg-node/fetch@^0.6.1` ↗︎](https://www.npmjs.com/package/@whatwg-node/fetch/v/0.6.1) (from `0.5.4`, in `dependencies`) diff --git a/.changeset/@graphql-yoga_urql-exchange-2266-dependencies.md b/.changeset/@graphql-yoga_urql-exchange-2266-dependencies.md new file mode 100644 index 0000000000..70b4679321 --- /dev/null +++ b/.changeset/@graphql-yoga_urql-exchange-2266-dependencies.md @@ -0,0 +1,5 @@ +--- +'@graphql-yoga/urql-exchange': patch +--- +dependencies updates: + - Updated dependency [`@graphql-tools/executor-http@0.0.8` ↗︎](https://www.npmjs.com/package/@graphql-tools/executor-http/v/0.0.8) (from `0.0.7`, in `dependencies`) diff --git a/.changeset/calm-jars-draw.md b/.changeset/calm-jars-draw.md new file mode 100644 index 0000000000..31b0854621 --- /dev/null +++ b/.changeset/calm-jars-draw.md @@ -0,0 +1,8 @@ +--- +'graphql-yoga': minor +'@graphql-yoga/plugin-apollo-inline-trace': patch +'@graphql-yoga/plugin-defer-stream': patch +'@graphql-yoga/plugin-apq': patch +--- + +Accept URL patterns like `/:path` and `*` in `graphqlEndpoint` diff --git a/.changeset/graphql-yoga-2266-dependencies.md b/.changeset/graphql-yoga-2266-dependencies.md new file mode 100644 index 0000000000..8a15522881 --- /dev/null +++ b/.changeset/graphql-yoga-2266-dependencies.md @@ -0,0 +1,6 @@ +--- +'graphql-yoga': patch +--- +dependencies updates: + - Updated dependency [`@whatwg-node/fetch@0.6.1` ↗︎](https://www.npmjs.com/package/@whatwg-node/fetch/v/0.6.1) (from `0.5.4`, in `dependencies`) + - Updated dependency [`@whatwg-node/server@0.5.3` ↗︎](https://www.npmjs.com/package/@whatwg-node/server/v/0.5.3) (from `0.5.1`, in `dependencies`) diff --git a/examples/bun/package.json b/examples/bun/package.json index 78d6f1916c..bba981f7d3 100644 --- a/examples/bun/package.json +++ b/examples/bun/package.json @@ -12,6 +12,6 @@ "graphql": "16.6.0" }, "devDependencies": { - "@whatwg-node/fetch": "0.5.4" + "@whatwg-node/fetch": "0.6.1" } } diff --git a/examples/error-handling/package.json b/examples/error-handling/package.json index 7128292d06..f996d16874 100644 --- a/examples/error-handling/package.json +++ b/examples/error-handling/package.json @@ -8,7 +8,7 @@ }, "dependencies": { "graphql-yoga": "3.2.1", - "@whatwg-node/fetch": "0.5.4", + "@whatwg-node/fetch": "0.6.1", "graphql": "^16.1.0" }, "devDependencies": { diff --git a/packages/graphql-yoga/__tests__/requests.spec.ts b/packages/graphql-yoga/__tests__/requests.spec.ts index bbf5c76964..309352e5bf 100644 --- a/packages/graphql-yoga/__tests__/requests.spec.ts +++ b/packages/graphql-yoga/__tests__/requests.spec.ts @@ -5,6 +5,7 @@ describe('requests', () => { typeDefs: /* GraphQL */ ` type Query { ping: String + requestUrl: String } type Mutation { echo(str: String): String @@ -13,6 +14,7 @@ describe('requests', () => { resolvers: { Query: { ping: () => 'pong', + requestUrl: (_, __, ctx) => ctx.request.url, }, Mutation: { echo(root, args) { @@ -35,6 +37,41 @@ describe('requests', () => { expect(response.status).toBe(404) }) + it('should support path patterns', async () => { + const yoga = createYoga({ + schema, + logging: false, + graphqlEndpoint: '/:version/:path', + }) + const response = await yoga.fetch('http://yoga/v1/mypath', { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ query: '{ requestUrl }' }), + }) + + expect(response.status).toBe(200) + const body = await response.json() + expect(body.errors).toBeUndefined() + expect(body.data.requestUrl).toBe('http://yoga/v1/mypath') + }) + + it('allows you to bypass endpoint check with wildcard', async () => { + const yoga = createYoga({ + schema, + logging: false, + graphqlEndpoint: '*', + }) + const response = await yoga.fetch('http://yoga/random', { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ query: '{ ping }' }), + }) + + expect(response.status).toBe(200) + const body = await response.json() + expect(body.errors).toBeUndefined() + expect(body.data.ping).toBe('pong') + }) it('should send basic query', async () => { const response = await yoga.fetch('http://yoga/test-graphql', { method: 'POST', diff --git a/packages/graphql-yoga/package.json b/packages/graphql-yoga/package.json index ca78a1dd6f..14b0cc58ec 100644 --- a/packages/graphql-yoga/package.json +++ b/packages/graphql-yoga/package.json @@ -56,8 +56,8 @@ "@graphql-tools/schema": "^9.0.0", "@graphql-tools/utils": "^9.0.1", "@graphql-yoga/subscription": "^3.0.0", - "@whatwg-node/fetch": "0.5.4", - "@whatwg-node/server": "0.5.1", + "@whatwg-node/fetch": "0.6.1", + "@whatwg-node/server": "0.5.3", "dset": "^3.1.1", "tslib": "^2.3.1" }, diff --git a/packages/graphql-yoga/src/plugins/useGraphiQL.ts b/packages/graphql-yoga/src/plugins/useGraphiQL.ts index 49ce9cd64a..8812ae0f6b 100644 --- a/packages/graphql-yoga/src/plugins/useGraphiQL.ts +++ b/packages/graphql-yoga/src/plugins/useGraphiQL.ts @@ -1,5 +1,4 @@ import { PromiseOrValue } from '@envelop/core' - import graphiqlHTML from '../graphiql-html.js' import { YogaLogger } from '../logger.js' import { Plugin } from './types.js' @@ -103,13 +102,15 @@ export function useGraphiQL>( } const renderer = config?.render ?? renderGraphiQL - + let urlPattern: URLPattern return { - async onRequest({ request, serverContext, fetchAPI, endResponse, url }) { - if ( - shouldRenderGraphiQL(request) && - config.graphqlEndpoint === url.pathname - ) { + async onRequest({ request, serverContext, fetchAPI, endResponse }) { + if (!urlPattern) { + urlPattern = new fetchAPI.URLPattern({ + pathname: config.graphqlEndpoint, + }) + } + if (shouldRenderGraphiQL(request) && urlPattern.test(request.url)) { logger.debug(`Rendering GraphiQL`) const graphiqlOptions = await graphiqlOptionsFactory( request, diff --git a/packages/graphql-yoga/src/plugins/useHealthCheck.ts b/packages/graphql-yoga/src/plugins/useHealthCheck.ts index 493c2b55ee..261ceafbf8 100644 --- a/packages/graphql-yoga/src/plugins/useHealthCheck.ts +++ b/packages/graphql-yoga/src/plugins/useHealthCheck.ts @@ -12,10 +12,13 @@ export function useHealthCheck({ logger = console, endpoint = '/health', }: HealthCheckPluginOptions = {}): Plugin { + let urlPattern: URLPattern return { - onRequest({ endResponse, fetchAPI, url }) { - const { pathname: requestPath } = url - if (requestPath === endpoint) { + onRequest({ request, endResponse, fetchAPI }) { + if (!urlPattern) { + urlPattern = new fetchAPI.URLPattern({ pathname: endpoint }) + } + if (urlPattern.test(request.url)) { logger.debug('Responding Health Check') const response = new fetchAPI.Response(null, { status: 200, diff --git a/packages/graphql-yoga/src/plugins/useReadinessCheck.ts b/packages/graphql-yoga/src/plugins/useReadinessCheck.ts index d53970cd5c..cbe0de5e35 100644 --- a/packages/graphql-yoga/src/plugins/useReadinessCheck.ts +++ b/packages/graphql-yoga/src/plugins/useReadinessCheck.ts @@ -34,10 +34,13 @@ export function useReadinessCheck({ endpoint = '/ready', check, }: ReadinessCheckPluginOptions): Plugin { + let urlPattern: URLPattern return { - async onRequest({ request, endResponse, fetchAPI, url }) { - const { pathname: requestPath } = url - if (requestPath === endpoint) { + async onRequest({ request, endResponse, fetchAPI }) { + if (!urlPattern) { + urlPattern = new fetchAPI.URLPattern({ pathname: endpoint }) + } + if (urlPattern.test(request.url)) { let response: Response try { const readyOrResponse = await check({ request, fetchAPI }) diff --git a/packages/graphql-yoga/src/plugins/useUnhandledRoute.ts b/packages/graphql-yoga/src/plugins/useUnhandledRoute.ts index 74063480e5..5763c35572 100644 --- a/packages/graphql-yoga/src/plugins/useUnhandledRoute.ts +++ b/packages/graphql-yoga/src/plugins/useUnhandledRoute.ts @@ -5,10 +5,13 @@ export function useUnhandledRoute(args: { graphqlEndpoint: string showLandingPage: boolean }): Plugin { + let urlPattern: URLPattern return { onRequest({ request, fetchAPI, endResponse, url }) { - const { pathname: requestPath } = url - if (requestPath !== args.graphqlEndpoint) { + if (!urlPattern) { + urlPattern = new fetchAPI.URLPattern({ pathname: args.graphqlEndpoint }) + } + if (!urlPattern.test(url)) { if ( args.showLandingPage === true && request.method === 'GET' && @@ -18,7 +21,7 @@ export function useUnhandledRoute(args: { new fetchAPI.Response( landingPageBody .replace(/__GRAPHIQL_LINK__/g, args.graphqlEndpoint) - .replace(/__REQUEST_PATH__/g, requestPath), + .replace(/__REQUEST_PATH__/g, url.pathname), { status: 200, statusText: 'OK', diff --git a/packages/graphql-yoga/src/server.ts b/packages/graphql-yoga/src/server.ts index b096b9e453..a3bb0e48c3 100644 --- a/packages/graphql-yoga/src/server.ts +++ b/packages/graphql-yoga/src/server.ts @@ -145,7 +145,7 @@ export type YogaServerOptions = { parserCache?: boolean | ParserCacheOptions validationCache?: boolean | ValidationCache - fetchAPI?: FetchAPI + fetchAPI?: Partial /** * GraphQL Multipart Request spec support * @@ -207,11 +207,10 @@ export class YogaServer< constructor(options?: YogaServerOptions) { this.id = options?.id ?? 'yoga' - this.fetchAPI = - options?.fetchAPI ?? - createFetch({ - useNodeFetch: true, - }) + const defaultFetchAPI = createFetch({ + useNodeFetch: true, + }) + this.fetchAPI = Object.assign(defaultFetchAPI, options?.fetchAPI ?? {}) const logger = options?.logging != null ? options.logging : true this.logger = diff --git a/packages/plugins/apollo-inline-trace/package.json b/packages/plugins/apollo-inline-trace/package.json index 2e5fc0fbdb..5b4d18aafa 100644 --- a/packages/plugins/apollo-inline-trace/package.json +++ b/packages/plugins/apollo-inline-trace/package.json @@ -42,7 +42,7 @@ }, "peerDependencies": { "@graphql-tools/utils": "^9.0.1", - "@whatwg-node/fetch": "^0.5.1", + "@whatwg-node/fetch": "^0.6.1", "graphql-yoga": "^3.2.1", "graphql": "^15.2.0 || ^16.0.0" }, @@ -51,8 +51,8 @@ "apollo-reporting-protobuf": "^3.3.2" }, "devDependencies": { - "@envelop/on-resolve": "^2.0.2", - "@whatwg-node/fetch": "^0.5.1", - "graphql-yoga": "^3.2.1" + "@envelop/on-resolve": "2.0.4", + "@whatwg-node/fetch": "0.6.1", + "graphql-yoga": "3.2.1" } } diff --git a/packages/plugins/apq/package.json b/packages/plugins/apq/package.json index f7f63b2d8a..f87500e8a6 100644 --- a/packages/plugins/apq/package.json +++ b/packages/plugins/apq/package.json @@ -40,11 +40,11 @@ "access": "public" }, "dependencies": { - "@whatwg-node/fetch": "0.5.4", + "@whatwg-node/fetch": "^0.6.1", "tiny-lru": "^10.0.0" }, "devDependencies": { - "graphql-yoga": "^3.2.1" + "graphql-yoga": "3.2.1" }, "peerDependencies": { "@graphql-tools/utils": "^9.0.1", diff --git a/packages/plugins/defer-stream/package.json b/packages/plugins/defer-stream/package.json index ecfaecae15..2159f78fb5 100644 --- a/packages/plugins/defer-stream/package.json +++ b/packages/plugins/defer-stream/package.json @@ -44,7 +44,7 @@ "graphql-yoga": "^3.2.1" }, "devDependencies": { - "@whatwg-node/fetch": "0.5.4" + "@whatwg-node/fetch": "0.6.1" }, "type": "module", "dependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b131067fd1..1f74022dbd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -207,7 +207,7 @@ importers: examples/bun: specifiers: - '@whatwg-node/fetch': 0.5.4 + '@whatwg-node/fetch': 0.6.1 bun-types: ^0.4.0 graphql: 16.6.0 graphql-yoga: 3.2.1 @@ -216,7 +216,7 @@ importers: graphql: 16.6.0 graphql-yoga: link:../../packages/graphql-yoga devDependencies: - '@whatwg-node/fetch': 0.5.4 + '@whatwg-node/fetch': 0.6.1 examples/cloudflare-advanced: specifiers: @@ -274,13 +274,13 @@ importers: examples/error-handling: specifiers: - '@whatwg-node/fetch': 0.5.4 + '@whatwg-node/fetch': 0.6.1 graphql: 16.6.0 graphql-yoga: 3.2.1 ts-node: 10.9.1 typescript: 4.9.4 dependencies: - '@whatwg-node/fetch': 0.5.4 + '@whatwg-node/fetch': 0.6.1 graphql: 16.6.0 graphql-yoga: link:../../packages/graphql-yoga devDependencies: @@ -884,8 +884,8 @@ importers: '@n1ru4l/in-memory-live-query-store': 0.10.0 '@repeaterjs/repeater': ^3.0.4 '@types/node': 18.11.18 - '@whatwg-node/fetch': 0.5.4 - '@whatwg-node/server': 0.5.1 + '@whatwg-node/fetch': 0.6.1 + '@whatwg-node/server': 0.5.3 dset: ^3.1.1 graphql: 16.6.0 graphql-http: ^1.7.2 @@ -902,8 +902,8 @@ importers: '@graphql-tools/schema': 9.0.4_graphql@16.6.0 '@graphql-tools/utils': 9.0.1_graphql@16.6.0 '@graphql-yoga/subscription': link:../subscription - '@whatwg-node/fetch': 0.5.4 - '@whatwg-node/server': 0.5.1_@types+node@18.11.18 + '@whatwg-node/fetch': 0.6.1 + '@whatwg-node/server': 0.5.3_@types+node@18.11.18 dset: 3.1.2 tslib: 2.4.0 devDependencies: @@ -934,24 +934,24 @@ importers: packages/plugins/apollo-inline-trace: specifiers: '@envelop/on-resolve': ^2.0.2 - '@whatwg-node/fetch': ^0.5.1 + '@whatwg-node/fetch': 0.6.1 apollo-reporting-protobuf: ^3.3.2 - graphql-yoga: ^3.2.1 + graphql-yoga: 3.2.1 dependencies: '@envelop/on-resolve': 2.0.2 apollo-reporting-protobuf: 3.3.3 devDependencies: - '@whatwg-node/fetch': 0.5.1 + '@whatwg-node/fetch': 0.6.1 graphql-yoga: link:../../graphql-yoga publishDirectory: dist packages/plugins/apq: specifiers: - '@whatwg-node/fetch': 0.5.4 - graphql-yoga: ^3.2.1 + '@whatwg-node/fetch': ^0.6.1 + graphql-yoga: 3.2.1 tiny-lru: ^10.0.0 dependencies: - '@whatwg-node/fetch': 0.5.4 + '@whatwg-node/fetch': 0.6.1 tiny-lru: 10.0.0 devDependencies: graphql-yoga: link:../../graphql-yoga @@ -960,11 +960,11 @@ importers: packages/plugins/defer-stream: specifiers: '@graphql-tools/utils': ^9.0.1 - '@whatwg-node/fetch': 0.5.4 + '@whatwg-node/fetch': 0.6.1 dependencies: '@graphql-tools/utils': 9.0.1 devDependencies: - '@whatwg-node/fetch': 0.5.4 + '@whatwg-node/fetch': 0.6.1 publishDirectory: dist packages/plugins/disable-introspection: @@ -9894,8 +9894,8 @@ packages: - encoding dev: true - /@whatwg-node/fetch/0.5.1: - resolution: {integrity: sha512-RBZS60EU6CbRJ370BVVKW4F9csZuGh0OQNrUDhJ0IaIFLsXsJorFCM2iwaDWZTAPMqxW1TmuVcVKJ3d/H1dV1g==} + /@whatwg-node/fetch/0.5.3: + resolution: {integrity: sha512-cuAKL3Z7lrJJuUrfF1wxkQTb24Qd1QO/lsjJpM5ZSZZzUMms5TPnbGeGUKWA3hVKNHh30lVfr2MyRCT5Jfkucw==} dependencies: '@peculiar/webcrypto': 1.4.0 abort-controller: 3.0.0 @@ -9907,10 +9907,10 @@ packages: web-streams-polyfill: 3.2.1 transitivePeerDependencies: - encoding - dev: true + dev: false - /@whatwg-node/fetch/0.5.3: - resolution: {integrity: sha512-cuAKL3Z7lrJJuUrfF1wxkQTb24Qd1QO/lsjJpM5ZSZZzUMms5TPnbGeGUKWA3hVKNHh30lVfr2MyRCT5Jfkucw==} + /@whatwg-node/fetch/0.5.4: + resolution: {integrity: sha512-dR5PCzvOeS7OaW6dpIlPt+Ou3pak7IEG+ZVAV26ltcaiDB3+IpuvjqRdhsY6FKHcqBo1qD+S99WXY9Z6+9Rwnw==} dependencies: '@peculiar/webcrypto': 1.4.0 abort-controller: 3.0.0 @@ -9922,10 +9922,9 @@ packages: web-streams-polyfill: 3.2.1 transitivePeerDependencies: - encoding - dev: false - /@whatwg-node/fetch/0.5.4: - resolution: {integrity: sha512-dR5PCzvOeS7OaW6dpIlPt+Ou3pak7IEG+ZVAV26ltcaiDB3+IpuvjqRdhsY6FKHcqBo1qD+S99WXY9Z6+9Rwnw==} + /@whatwg-node/fetch/0.6.1: + resolution: {integrity: sha512-sG39WLvcJxGZ+gDstnLSXR2IcnuvIOB51KxCFo0mEhFW0q2u8fZgolr0HPkL+zXwOJsnmT+9V3IRcqLnTXdqVQ==} dependencies: '@peculiar/webcrypto': 1.4.0 abort-controller: 3.0.0 @@ -9934,6 +9933,7 @@ packages: formdata-node: 4.4.1_bwnmzlpvx75llwj7xwqbxbjtui node-fetch: 2.6.7 undici: 5.12.0 + urlpattern-polyfill: 6.0.2 web-streams-polyfill: 3.2.1 transitivePeerDependencies: - encoding @@ -9949,13 +9949,13 @@ packages: - encoding dev: false - /@whatwg-node/server/0.5.1_@types+node@18.11.18: - resolution: {integrity: sha512-0xhGUnMYwRulGduMXSyiZvn182U2ma4V+plM/M4Yg/ZjGu0DbOi/LW4huZlNsDmmxVYpPluX0p7IT4ZzGzbPEA==} + /@whatwg-node/server/0.5.3_@types+node@18.11.18: + resolution: {integrity: sha512-Iq3B8Mjiqb4YNazAM7dltGpvcubBJfpDLVqGzelCaVZ2mtGdMgmGUVfDilftQnWYtX0fOyM4+gdHGNexrNuBeg==} peerDependencies: '@types/node': ^18.0.6 dependencies: '@types/node': 18.11.18 - '@whatwg-node/fetch': 0.5.4 + '@whatwg-node/fetch': 0.6.1 tslib: 2.4.1 transitivePeerDependencies: - encoding @@ -26454,6 +26454,11 @@ packages: resolution: {integrity: sha512-DOE84vZT2fEcl9gqCUTcnAw5ZY5Id55ikUcziSUntuEFL3pRvavg5kwDmTEUJkeCHInTlV/HexFomgYnzO5kdQ==} dev: true + /urlpattern-polyfill/6.0.2: + resolution: {integrity: sha512-5vZjFlH9ofROmuWmXM9yj2wljYKgWstGwe8YTyiqM7hVum/g9LyCizPZtb3UqsuppVwety9QJmfc42VggLpTgg==} + dependencies: + braces: 3.0.2 + /use-callback-ref/1.3.0_kzbn2opkn2327fwg5yzwzya5o4: resolution: {integrity: sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==} engines: {node: '>=10'}