diff --git a/.changeset/@graphql-hive_gateway-1608-dependencies.md b/.changeset/@graphql-hive_gateway-1608-dependencies.md new file mode 100644 index 000000000..105383ef0 --- /dev/null +++ b/.changeset/@graphql-hive_gateway-1608-dependencies.md @@ -0,0 +1,35 @@ +--- +'@graphql-hive/gateway': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-mesh/cache-cfw-kv@^0.105.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/cache-cfw-kv/v/0.105.14) (from `^0.105.13`, in `dependencies`) +- Updated dependency [`@graphql-mesh/cache-localforage@^0.105.15` ↗︎](https://www.npmjs.com/package/@graphql-mesh/cache-localforage/v/0.105.15) (from `^0.105.14`, in `dependencies`) +- Updated dependency [`@graphql-mesh/cache-redis@^0.105.0` ↗︎](https://www.npmjs.com/package/@graphql-mesh/cache-redis/v/0.105.0) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-mesh/cache-upstash-redis@^0.1.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/cache-upstash-redis/v/0.1.14) (from `^0.1.13`, in `dependencies`) +- Updated dependency [`@graphql-mesh/plugin-http-cache@^0.105.15` ↗︎](https://www.npmjs.com/package/@graphql-mesh/plugin-http-cache/v/0.105.15) (from `^0.105.14`, in `dependencies`) +- Updated dependency [`@graphql-mesh/plugin-jit@^0.2.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/plugin-jit/v/0.2.14) (from `^0.2.13`, in `dependencies`) +- Updated dependency [`@graphql-mesh/plugin-rate-limit@^0.105.2` ↗︎](https://www.npmjs.com/package/@graphql-mesh/plugin-rate-limit/v/0.105.2) (from `^0.105.1`, in `dependencies`) +- Updated dependency [`@graphql-mesh/plugin-snapshot@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/plugin-snapshot/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-mesh/types@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/types/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-mesh/utils@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/utils/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-tools/code-file-loader@^8.1.24` ↗︎](https://www.npmjs.com/package/@graphql-tools/code-file-loader/v/8.1.24) (from `^8.1.22`, in `dependencies`) +- Updated dependency [`@graphql-tools/graphql-file-loader@^8.1.4` ↗︎](https://www.npmjs.com/package/@graphql-tools/graphql-file-loader/v/8.1.4) (from `^8.1.2`, in `dependencies`) +- Updated dependency [`@graphql-tools/load@^8.1.4` ↗︎](https://www.npmjs.com/package/@graphql-tools/load/v/8.1.4) (from `^8.1.2`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) +- Updated dependency [`@graphql-yoga/render-graphiql@^5.16.1` ↗︎](https://www.npmjs.com/package/@graphql-yoga/render-graphiql/v/5.16.1) (from `^5.16.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/api-logs@^0.207.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/api-logs/v/0.207.0) (from `^0.206.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/context-async-hooks@^2.2.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/context-async-hooks/v/2.2.0) (from `^2.1.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/context-zone@^2.2.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/context-zone/v/2.2.0) (from `^2.1.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/core@^2.2.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/core/v/2.2.0) (from `^2.1.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/exporter-jaeger@^2.2.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/exporter-jaeger/v/2.2.0) (from `^2.1.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/exporter-zipkin@^2.2.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/exporter-zipkin/v/2.2.0) (from `^2.1.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/propagator-b3@^2.2.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/propagator-b3/v/2.2.0) (from `^2.1.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/propagator-jaeger@^2.2.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/propagator-jaeger/v/2.2.0) (from `^2.1.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/sampler-jaeger-remote@^0.207.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/sampler-jaeger-remote/v/0.207.0) (from `^0.206.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/sdk-logs@^0.207.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/sdk-logs/v/0.207.0) (from `^0.206.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/sdk-metrics@^2.2.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/sdk-metrics/v/2.2.0) (from `^2.1.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/sdk-trace-base@^2.2.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/sdk-trace-base/v/2.2.0) (from `^2.1.0`, in `dependencies`) +- Updated dependency [`commander@^14.0.2` ↗︎](https://www.npmjs.com/package/commander/v/14.0.2) (from `^14.0.1`, in `dependencies`) +- Updated dependency [`graphql-yoga@^5.16.1` ↗︎](https://www.npmjs.com/package/graphql-yoga/v/5.16.1) (from `^5.16.0`, in `dependencies`) diff --git a/.changeset/@graphql-hive_gateway-runtime-1608-dependencies.md b/.changeset/@graphql-hive_gateway-runtime-1608-dependencies.md new file mode 100644 index 000000000..55c8cc322 --- /dev/null +++ b/.changeset/@graphql-hive_gateway-runtime-1608-dependencies.md @@ -0,0 +1,17 @@ +--- +'@graphql-hive/gateway-runtime': patch +--- + +dependencies updates: + +- Updated dependency [`@envelop/generic-auth@^10.0.1` ↗︎](https://www.npmjs.com/package/@envelop/generic-auth/v/10.0.1) (from `^10.0.0`, in `dependencies`) +- Updated dependency [`@graphql-mesh/plugin-response-cache@^0.104.15` ↗︎](https://www.npmjs.com/package/@graphql-mesh/plugin-response-cache/v/0.104.15) (from `^0.104.14`, in `dependencies`) +- Updated dependency [`@graphql-mesh/types@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/types/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-mesh/utils@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/utils/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) +- Updated dependency [`@graphql-yoga/plugin-apollo-usage-report@^0.11.1` ↗︎](https://www.npmjs.com/package/@graphql-yoga/plugin-apollo-usage-report/v/0.11.1) (from `^0.11.0`, in `dependencies`) +- Updated dependency [`@graphql-yoga/plugin-csrf-prevention@^3.16.1` ↗︎](https://www.npmjs.com/package/@graphql-yoga/plugin-csrf-prevention/v/3.16.1) (from `^3.16.0`, in `dependencies`) +- Updated dependency [`@graphql-yoga/plugin-defer-stream@^3.16.1` ↗︎](https://www.npmjs.com/package/@graphql-yoga/plugin-defer-stream/v/3.16.1) (from `^3.16.0`, in `dependencies`) +- Updated dependency [`@graphql-yoga/plugin-persisted-operations@^3.16.1` ↗︎](https://www.npmjs.com/package/@graphql-yoga/plugin-persisted-operations/v/3.16.1) (from `^3.16.0`, in `dependencies`) +- Updated dependency [`@types/node@^24.10.0` ↗︎](https://www.npmjs.com/package/@types/node/v/24.10.0) (from `^24.7.2`, in `dependencies`) +- Updated dependency [`graphql-yoga@^5.16.1` ↗︎](https://www.npmjs.com/package/graphql-yoga/v/5.16.1) (from `^5.16.0`, in `dependencies`) diff --git a/.changeset/@graphql-hive_logger-1608-dependencies.md b/.changeset/@graphql-hive_logger-1608-dependencies.md new file mode 100644 index 000000000..8f2eab050 --- /dev/null +++ b/.changeset/@graphql-hive_logger-1608-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-hive/logger': patch +--- + +dependencies updates: + +- Updated dependency [`@logtape/logtape@^1.1.2` ↗︎](https://www.npmjs.com/package/@logtape/logtape/v/1.1.2) (from `^1.1.1`, in `peerDependencies`) diff --git a/.changeset/@graphql-hive_nestjs-1608-dependencies.md b/.changeset/@graphql-hive_nestjs-1608-dependencies.md new file mode 100644 index 000000000..d01e02eca --- /dev/null +++ b/.changeset/@graphql-hive_nestjs-1608-dependencies.md @@ -0,0 +1,8 @@ +--- +'@graphql-hive/nestjs': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-mesh/types@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/types/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) diff --git a/.changeset/@graphql-hive_plugin-aws-sigv4-1608-dependencies.md b/.changeset/@graphql-hive_plugin-aws-sigv4-1608-dependencies.md new file mode 100644 index 000000000..6d13dece3 --- /dev/null +++ b/.changeset/@graphql-hive_plugin-aws-sigv4-1608-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-hive/plugin-aws-sigv4': patch +--- + +dependencies updates: + +- Updated dependency [`@aws-sdk/client-sts@^3.925.0` ↗︎](https://www.npmjs.com/package/@aws-sdk/client-sts/v/3.925.0) (from `^3.908.0`, in `dependencies`) diff --git a/.changeset/@graphql-hive_plugin-deduplicate-request-1608-dependencies.md b/.changeset/@graphql-hive_plugin-deduplicate-request-1608-dependencies.md new file mode 100644 index 000000000..bff68a5d6 --- /dev/null +++ b/.changeset/@graphql-hive_plugin-deduplicate-request-1608-dependencies.md @@ -0,0 +1,9 @@ +--- +'@graphql-hive/plugin-deduplicate-request': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-mesh/utils@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/utils/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) +- Updated dependency [`graphql@^16.12.0` ↗︎](https://www.npmjs.com/package/graphql/v/16.12.0) (from `^16.9.0`, in `peerDependencies`) diff --git a/.changeset/@graphql-hive_plugin-opentelemetry-1608-dependencies.md b/.changeset/@graphql-hive_plugin-opentelemetry-1608-dependencies.md new file mode 100644 index 000000000..339d524e8 --- /dev/null +++ b/.changeset/@graphql-hive_plugin-opentelemetry-1608-dependencies.md @@ -0,0 +1,20 @@ +--- +'@graphql-hive/plugin-opentelemetry': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-mesh/types@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/types/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-mesh/utils@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/utils/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) +- Updated dependency [`@opentelemetry/api-logs@^0.207.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/api-logs/v/0.207.0) (from `^0.206.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/auto-instrumentations-node@^0.66.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node/v/0.66.0) (from `^0.65.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/context-async-hooks@^2.2.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/context-async-hooks/v/2.2.0) (from `^2.1.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/core@^2.2.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/core/v/2.2.0) (from `^2.1.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/exporter-trace-otlp-grpc@^0.207.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-grpc/v/0.207.0) (from `^0.206.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/exporter-trace-otlp-http@^0.207.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-http/v/0.207.0) (from `^0.206.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/instrumentation@^0.207.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/instrumentation/v/0.207.0) (from `^0.206.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/resources@^2.2.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/resources/v/2.2.0) (from `^2.1.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/sdk-logs@^0.207.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/sdk-logs/v/0.207.0) (from `^0.206.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/sdk-node@^0.207.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/sdk-node/v/0.207.0) (from `^0.206.0`, in `dependencies`) +- Updated dependency [`@opentelemetry/sdk-trace-base@^2.2.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/sdk-trace-base/v/2.2.0) (from `^2.1.0`, in `dependencies`) diff --git a/.changeset/@graphql-mesh_fusion-runtime-1608-dependencies.md b/.changeset/@graphql-mesh_fusion-runtime-1608-dependencies.md new file mode 100644 index 000000000..83e5f3ca4 --- /dev/null +++ b/.changeset/@graphql-mesh_fusion-runtime-1608-dependencies.md @@ -0,0 +1,12 @@ +--- +'@graphql-mesh/fusion-runtime': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-mesh/types@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/types/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-mesh/utils@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/utils/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-tools/executor@^1.4.11` ↗︎](https://www.npmjs.com/package/@graphql-tools/executor/v/1.4.11) (from `^1.4.9`, in `dependencies`) +- Updated dependency [`@graphql-tools/merge@^9.1.3` ↗︎](https://www.npmjs.com/package/@graphql-tools/merge/v/9.1.3) (from `^9.1.1`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) +- Updated dependency [`graphql-yoga@^5.16.1` ↗︎](https://www.npmjs.com/package/graphql-yoga/v/5.16.1) (from `^5.16.0`, in `dependencies`) diff --git a/.changeset/@graphql-mesh_hmac-upstream-signature-1608-dependencies.md b/.changeset/@graphql-mesh_hmac-upstream-signature-1608-dependencies.md new file mode 100644 index 000000000..55d790050 --- /dev/null +++ b/.changeset/@graphql-mesh_hmac-upstream-signature-1608-dependencies.md @@ -0,0 +1,9 @@ +--- +'@graphql-mesh/hmac-upstream-signature': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-mesh/types@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/types/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-mesh/utils@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/utils/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) diff --git a/.changeset/@graphql-mesh_plugin-jwt-auth-1608-dependencies.md b/.changeset/@graphql-mesh_plugin-jwt-auth-1608-dependencies.md new file mode 100644 index 000000000..7ac63d1d2 --- /dev/null +++ b/.changeset/@graphql-mesh_plugin-jwt-auth-1608-dependencies.md @@ -0,0 +1,9 @@ +--- +'@graphql-mesh/plugin-jwt-auth': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-mesh/types@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/types/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-mesh/utils@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/utils/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-yoga/plugin-jwt@^3.10.1` ↗︎](https://www.npmjs.com/package/@graphql-yoga/plugin-jwt/v/3.10.1) (from `^3.10.0`, in `dependencies`) diff --git a/.changeset/@graphql-mesh_plugin-prometheus-1608-dependencies.md b/.changeset/@graphql-mesh_plugin-prometheus-1608-dependencies.md new file mode 100644 index 000000000..51b981a90 --- /dev/null +++ b/.changeset/@graphql-mesh_plugin-prometheus-1608-dependencies.md @@ -0,0 +1,10 @@ +--- +'@graphql-mesh/plugin-prometheus': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-mesh/types@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/types/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-mesh/utils@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/utils/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) +- Updated dependency [`@graphql-yoga/plugin-prometheus@^6.11.1` ↗︎](https://www.npmjs.com/package/@graphql-yoga/plugin-prometheus/v/6.11.1) (from `^6.11.0`, in `dependencies`) diff --git a/.changeset/@graphql-mesh_transport-common-1608-dependencies.md b/.changeset/@graphql-mesh_transport-common-1608-dependencies.md new file mode 100644 index 000000000..343d58e11 --- /dev/null +++ b/.changeset/@graphql-mesh_transport-common-1608-dependencies.md @@ -0,0 +1,9 @@ +--- +'@graphql-mesh/transport-common': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-mesh/types@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/types/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-tools/executor@^1.4.11` ↗︎](https://www.npmjs.com/package/@graphql-tools/executor/v/1.4.11) (from `^1.4.9`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) diff --git a/.changeset/@graphql-mesh_transport-http-1608-dependencies.md b/.changeset/@graphql-mesh_transport-http-1608-dependencies.md new file mode 100644 index 000000000..9acd9f34e --- /dev/null +++ b/.changeset/@graphql-mesh_transport-http-1608-dependencies.md @@ -0,0 +1,10 @@ +--- +'@graphql-mesh/transport-http': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-mesh/types@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/types/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-mesh/utils@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/utils/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) +- Removed dependency [`graphql@^16.9.0` ↗︎](https://www.npmjs.com/package/graphql/v/16.9.0) (from `dependencies`) diff --git a/.changeset/@graphql-mesh_transport-http-callback-1608-dependencies.md b/.changeset/@graphql-mesh_transport-http-callback-1608-dependencies.md new file mode 100644 index 000000000..e0448face --- /dev/null +++ b/.changeset/@graphql-mesh_transport-http-callback-1608-dependencies.md @@ -0,0 +1,10 @@ +--- +'@graphql-mesh/transport-http-callback': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-mesh/types@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/types/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-mesh/utils@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/utils/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) +- Updated dependency [`@whatwg-node/fetch@^0.10.12` ↗︎](https://www.npmjs.com/package/@whatwg-node/fetch/v/0.10.12) (from `^0.10.11`, in `dependencies`) diff --git a/.changeset/@graphql-mesh_transport-ws-1608-dependencies.md b/.changeset/@graphql-mesh_transport-ws-1608-dependencies.md new file mode 100644 index 000000000..3aebb6193 --- /dev/null +++ b/.changeset/@graphql-mesh_transport-ws-1608-dependencies.md @@ -0,0 +1,9 @@ +--- +'@graphql-mesh/transport-ws': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-mesh/types@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/types/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-mesh/utils@^0.104.14` ↗︎](https://www.npmjs.com/package/@graphql-mesh/utils/v/0.104.14) (from `^0.104.13`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) diff --git a/.changeset/@graphql-tools_batch-delegate-1608-dependencies.md b/.changeset/@graphql-tools_batch-delegate-1608-dependencies.md new file mode 100644 index 000000000..2ef0975c4 --- /dev/null +++ b/.changeset/@graphql-tools_batch-delegate-1608-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-tools/batch-delegate': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) diff --git a/.changeset/@graphql-tools_batch-execute-1608-dependencies.md b/.changeset/@graphql-tools_batch-execute-1608-dependencies.md new file mode 100644 index 000000000..75750af51 --- /dev/null +++ b/.changeset/@graphql-tools_batch-execute-1608-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-tools/batch-execute': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) diff --git a/.changeset/@graphql-tools_delegate-1608-dependencies.md b/.changeset/@graphql-tools_delegate-1608-dependencies.md new file mode 100644 index 000000000..5f624266d --- /dev/null +++ b/.changeset/@graphql-tools_delegate-1608-dependencies.md @@ -0,0 +1,10 @@ +--- +'@graphql-tools/delegate': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/executor@^1.4.11` ↗︎](https://www.npmjs.com/package/@graphql-tools/executor/v/1.4.11) (from `^1.4.9`, in `dependencies`) +- Updated dependency [`@graphql-tools/schema@^10.0.27` ↗︎](https://www.npmjs.com/package/@graphql-tools/schema/v/10.0.27) (from `^10.0.25`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) +- Removed dependency [`dset@^3.1.2` ↗︎](https://www.npmjs.com/package/dset/v/3.1.2) (from `dependencies`) diff --git a/.changeset/@graphql-tools_executor-common-1608-dependencies.md b/.changeset/@graphql-tools_executor-common-1608-dependencies.md new file mode 100644 index 000000000..2225ce242 --- /dev/null +++ b/.changeset/@graphql-tools_executor-common-1608-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-tools/executor-common': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) diff --git a/.changeset/@graphql-tools_executor-graphql-ws-1608-dependencies.md b/.changeset/@graphql-tools_executor-graphql-ws-1608-dependencies.md new file mode 100644 index 000000000..bcad5b4f9 --- /dev/null +++ b/.changeset/@graphql-tools_executor-graphql-ws-1608-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-tools/executor-graphql-ws': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) diff --git a/.changeset/@graphql-tools_executor-http-1608-dependencies.md b/.changeset/@graphql-tools_executor-http-1608-dependencies.md new file mode 100644 index 000000000..d5f5e0afe --- /dev/null +++ b/.changeset/@graphql-tools_executor-http-1608-dependencies.md @@ -0,0 +1,8 @@ +--- +'@graphql-tools/executor-http': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) +- Updated dependency [`@whatwg-node/fetch@^0.10.12` ↗︎](https://www.npmjs.com/package/@whatwg-node/fetch/v/0.10.12) (from `^0.10.11`, in `dependencies`) diff --git a/.changeset/@graphql-tools_federation-1608-dependencies.md b/.changeset/@graphql-tools_federation-1608-dependencies.md new file mode 100644 index 000000000..3424e03da --- /dev/null +++ b/.changeset/@graphql-tools_federation-1608-dependencies.md @@ -0,0 +1,11 @@ +--- +'@graphql-tools/federation': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/executor@^1.4.11` ↗︎](https://www.npmjs.com/package/@graphql-tools/executor/v/1.4.11) (from `^1.4.9`, in `dependencies`) +- Updated dependency [`@graphql-tools/merge@^9.1.3` ↗︎](https://www.npmjs.com/package/@graphql-tools/merge/v/9.1.3) (from `^9.1.1`, in `dependencies`) +- Updated dependency [`@graphql-tools/schema@^10.0.27` ↗︎](https://www.npmjs.com/package/@graphql-tools/schema/v/10.0.27) (from `^10.0.25`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) +- Updated dependency [`@whatwg-node/fetch@^0.10.12` ↗︎](https://www.npmjs.com/package/@whatwg-node/fetch/v/0.10.12) (from `^0.10.11`, in `dependencies`) diff --git a/.changeset/@graphql-tools_stitch-1608-dependencies.md b/.changeset/@graphql-tools_stitch-1608-dependencies.md new file mode 100644 index 000000000..9f3b22d48 --- /dev/null +++ b/.changeset/@graphql-tools_stitch-1608-dependencies.md @@ -0,0 +1,10 @@ +--- +'@graphql-tools/stitch': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/executor@^1.4.11` ↗︎](https://www.npmjs.com/package/@graphql-tools/executor/v/1.4.11) (from `^1.4.9`, in `dependencies`) +- Updated dependency [`@graphql-tools/merge@^9.1.3` ↗︎](https://www.npmjs.com/package/@graphql-tools/merge/v/9.1.3) (from `^9.1.1`, in `dependencies`) +- Updated dependency [`@graphql-tools/schema@^10.0.27` ↗︎](https://www.npmjs.com/package/@graphql-tools/schema/v/10.0.27) (from `^10.0.25`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) diff --git a/.changeset/@graphql-tools_stitching-directives-1608-dependencies.md b/.changeset/@graphql-tools_stitching-directives-1608-dependencies.md new file mode 100644 index 000000000..13746a027 --- /dev/null +++ b/.changeset/@graphql-tools_stitching-directives-1608-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-tools/stitching-directives': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) diff --git a/.changeset/@graphql-tools_wrap-1608-dependencies.md b/.changeset/@graphql-tools_wrap-1608-dependencies.md new file mode 100644 index 000000000..2d9c2b41e --- /dev/null +++ b/.changeset/@graphql-tools_wrap-1608-dependencies.md @@ -0,0 +1,8 @@ +--- +'@graphql-tools/wrap': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/schema@^10.0.27` ↗︎](https://www.npmjs.com/package/@graphql-tools/schema/v/10.0.27) (from `^10.0.25`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.9.1`, in `dependencies`) diff --git a/packages/runtime/src/createGatewayRuntime.ts b/packages/runtime/src/createGatewayRuntime.ts index 615387cd7..2530d33ca 100644 --- a/packages/runtime/src/createGatewayRuntime.ts +++ b/packages/runtime/src/createGatewayRuntime.ts @@ -1053,6 +1053,13 @@ export function createGatewayRuntime< } if (config.demandControl) { + if ('proxy' in config && config.schema == null) { + log.warn( + '`demandControl` is enabled in proxy mode without a defined schema' + + 'If you use directives like "@cost" or "@listSize", these won\'t be available for cost calculation.' + + 'You have to define "schema" in the gateway config to make them available.', + ); + } extraPlugins.push(useDemandControl(config.demandControl)); } diff --git a/packages/runtime/src/plugins/useDemandControl.ts b/packages/runtime/src/plugins/useDemandControl.ts index 649f03ff4..f20efc849 100644 --- a/packages/runtime/src/plugins/useDemandControl.ts +++ b/packages/runtime/src/plugins/useDemandControl.ts @@ -70,6 +70,9 @@ export function useDemandControl>({ const costByContextMap = new WeakMap(); return { onSubgraphExecute({ subgraph, executionRequest, log }) { + if (!subgraph) { + return; + } let costByContext = executionRequest.context ? costByContextMap.get(executionRequest.context) || 0 : 0; diff --git a/packages/runtime/tests/demand-control.test.ts b/packages/runtime/tests/demand-control.test.ts index a33e9534c..666f97589 100644 --- a/packages/runtime/tests/demand-control.test.ts +++ b/packages/runtime/tests/demand-control.test.ts @@ -4,7 +4,7 @@ import { useCustomFetch, } from '@graphql-hive/gateway-runtime'; import { composeLocalSchemasWithApollo } from '@internal/testing'; -import { parse } from 'graphql'; +import { GraphQLSchema, parse } from 'graphql'; import { createYoga } from 'graphql-yoga'; import { describe, expect, it } from 'vitest'; import { useDemandControl } from '../src/plugins/useDemandControl'; @@ -22,1168 +22,1099 @@ describe('Demand Control', () => { }, }, }; - /** - * 1 Query (0) + 1 book object (1) + 1 author object (1) + 1 publisher object (1) + 1 address object (1) = 4 total cost - */ - it('basic query', async () => { - const booksSubgraph = buildSubgraphSchema({ - typeDefs: parse(/* GraphQL */ ` - type Query { - book(id: ID): Book - } + type TestGatewayMode = 'proxy' | 'supergraph'; + function createTestGateway( + mode: TestGatewayMode, + subgraph: GraphQLSchema, + demandControlConfig: Parameters[0] = { + includeExtensionMetadata: true, + }, + introspectFromEndpoint = false, + ) { + const subgraphServer = createYoga({ + schema: subgraph, + }); + const plugins = () => [ + // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch + useCustomFetch(subgraphServer.fetch), + useDemandControl(demandControlConfig), + ]; + return mode === 'proxy' + ? createGatewayRuntime({ + proxy: { + endpoint: 'http://upstream/graphql', + }, + schema: introspectFromEndpoint ? undefined : subgraph, + plugins, + }) + : createGatewayRuntime({ + supergraph: composeLocalSchemasWithApollo([ + { + name: 'subgraph', + schema: subgraph, + url: 'http://subgraph/graphql', + }, + ]), + plugins, + }); + } + const testModes: TestGatewayMode[] = ['proxy', 'supergraph']; + testModes.forEach((mode: TestGatewayMode) => { + describe(`in ${mode} mode`, () => { + /** + * 1 Query (0) + 1 book object (1) + 1 author object (1) + 1 publisher object (1) + 1 address object (1) = 4 total cost + */ + it('basic query', async () => { + const booksSubgraph = buildSubgraphSchema({ + typeDefs: parse(/* GraphQL */ ` + type Query { + book(id: ID): Book + } - type Book { - title: String - author: Author - publisher: Publisher - } + type Book { + title: String + author: Author + publisher: Publisher + } - type Author { - name: String - } + type Author { + name: String + } - type Publisher { - name: String - address: Address - } + type Publisher { + name: String + address: Address + } - type Address { - zipCode: Int! - } - `), - resolvers: { - Query: { - book: (_root, { id }) => { - if (id === '1') { - return book; + type Address { + zipCode: Int! } - throw new Error('Book not found'); + `), + resolvers: { + Query: { + book: (_root, { id }) => { + if (id === '1') { + return book; + } + throw new Error('Book not found'); + }, + }, }, - }, - }, - }); - await using booksServer = createYoga({ - schema: booksSubgraph, - }); - await using gateway = createGatewayRuntime({ - supergraph: await composeLocalSchemasWithApollo([ - { - name: 'books', - schema: booksSubgraph, - url: 'http://books/graphql', - }, - ]), - plugins: () => [ - // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch - useCustomFetch(booksServer.fetch), - useDemandControl({ - includeExtensionMetadata: true, - }), - ], - }); - const query = /* GraphQL */ ` - query BookQuery { - book(id: 1) { - title - author { - name - } - publisher { - name - address { - zipCode + }); + await using gateway = createTestGateway(mode, booksSubgraph); + const query = /* GraphQL */ ` + query BookQuery { + book(id: 1) { + title + author { + name + } + publisher { + name + address { + zipCode + } + } } } - } - } - `; - const response = await gateway.fetch('http://localhost:4000/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query }), - }); - const result = await response.json(); - expect(result).toEqual({ - data: { - book, - }, - extensions: { - cost: { - estimated: 4, - }, - }, - }); - }); - /** - * 1 Query (0) + 1 book object (1) + 1 author object (1) + 1 publisher object (1) + 1 address object (5) = 8 total cost - */ - it('@cost in object', async () => { - const booksSubgraph = buildSubgraphSchema({ - typeDefs: parse(/* GraphQL */ ` - type Query { - book(id: ID): Book - } + `; + const response = await gateway.fetch('http://localhost:4000/graphql', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ query }), + }); + const result = await response.json(); + expect(result).toEqual({ + data: { + book, + }, + extensions: { + cost: { + estimated: 4, + }, + }, + }); + }); + /** + * 1 Query (0) + 1 book object (1) + 1 author object (1) + 1 publisher object (1) + 1 address object (5) = 8 total cost + */ + it('@cost in object', async () => { + const booksSubgraph = buildSubgraphSchema({ + typeDefs: parse(/* GraphQL */ ` + type Query { + book(id: ID): Book + } - type Book { - title: String - author: Author - publisher: Publisher - } + type Book { + title: String + author: Author + publisher: Publisher + } - type Author { - name: String - } + type Author { + name: String + } - type Publisher { - name: String - address: Address - } + type Publisher { + name: String + address: Address + } - type Address @cost(weight: 5) { - zipCode: Int! - } - extend schema - @link( - url: "https://specs.apollo.dev/federation/v2.9" - import: ["@cost"] - ) { - query: Query - } - `), - resolvers: { - Query: { - book: (_root, { id }) => { - if (id === '1') { - return book; + type Address @cost(weight: 5) { + zipCode: Int! + } + extend schema + @link( + url: "https://specs.apollo.dev/federation/v2.9" + import: ["@cost"] + ) { + query: Query } - throw new Error('Book not found'); + `), + resolvers: { + Query: { + book: (_root, { id }) => { + if (id === '1') { + return book; + } + throw new Error('Book not found'); + }, + }, }, - }, - }, - }); - await using booksServer = createYoga({ - schema: booksSubgraph, - }); - await using gateway = createGatewayRuntime({ - supergraph: await composeLocalSchemasWithApollo([ - { - name: 'books', - schema: booksSubgraph, - url: 'http://books/graphql', - }, - ]), - plugins: () => [ - // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch - useCustomFetch(booksServer.fetch), - useDemandControl({ - includeExtensionMetadata: true, - }), - ], - }); - const query = /* GraphQL */ ` - query BookQuery { - book(id: 1) { - title - author { - name - } - publisher { - name - address { - zipCode + }); + await using gateway = createTestGateway(mode, booksSubgraph); + const query = /* GraphQL */ ` + query BookQuery { + book(id: 1) { + title + author { + name + } + publisher { + name + address { + zipCode + } + } } } - } - } - `; - const response = await gateway.fetch('http://localhost:4000/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query }), - }); - const result = await response.json(); - expect(result).toEqual({ - data: { - book, - }, - extensions: { - cost: { - estimated: 8, - }, - }, - }); - }); - /** - * 1 Query (0) + 5 book objects (5 * (1 book object (1) + 1 author object (1) + 1 publisher object (1) + 1 address object (5))) = 40 total cost - */ - it('@listSize(assumedSize:)', async () => { - const booksSubgraph = buildSubgraphSchema({ - typeDefs: parse(/* GraphQL */ ` - type Query { - bestsellers: [Book] @listSize(assumedSize: 5) - } + `; + const response = await gateway.fetch('http://localhost:4000/graphql', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ query }), + }); + const result = await response.json(); + expect(result).toEqual({ + data: { + book, + }, + extensions: { + cost: { + estimated: 8, + }, + }, + }); + }); + /** + * 1 Query (0) + 5 book objects (5 * (1 book object (1) + 1 author object (1) + 1 publisher object (1) + 1 address object (5))) = 40 total cost + */ + it('@listSize(assumedSize:)', async () => { + const booksSubgraph = buildSubgraphSchema({ + typeDefs: parse(/* GraphQL */ ` + type Query { + bestsellers: [Book] @listSize(assumedSize: 5) + } - type Book { - title: String - author: Author - publisher: Publisher - } + type Book { + title: String + author: Author + publisher: Publisher + } - type Author { - name: String - } + type Author { + name: String + } - type Publisher { - name: String - address: Address - } + type Publisher { + name: String + address: Address + } - type Address @cost(weight: 5) { - zipCode: Int! - } - extend schema - @link( - url: "https://specs.apollo.dev/federation/v2.9" - import: ["@cost", "@listSize"] - ) { - query: Query - } - `), - resolvers: { - Query: { - book: (_root, { id }) => { - if (id === '1') { - return book; + type Address @cost(weight: 5) { + zipCode: Int! } - throw new Error('Book not found'); + extend schema + @link( + url: "https://specs.apollo.dev/federation/v2.9" + import: ["@cost", "@listSize"] + ) { + query: Query + } + `), + resolvers: { + Query: { + book: (_root, { id }) => { + if (id === '1') { + return book; + } + throw new Error('Book not found'); + }, + bestsellers: () => [book], + }, }, - bestsellers: () => [book], - }, - }, - }); - await using booksServer = createYoga({ - schema: booksSubgraph, - }); - await using gateway = createGatewayRuntime({ - supergraph: await composeLocalSchemasWithApollo([ - { - name: 'books', - schema: booksSubgraph, - url: 'http://books/graphql', - }, - ]), - plugins: () => [ - // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch - useCustomFetch(booksServer.fetch), - useDemandControl({ - includeExtensionMetadata: true, - }), - ], - }); - const query = /* GraphQL */ ` - query BestsellersQuery { - bestsellers { - title - author { - name - } - publisher { - name - address { - zipCode + }); + await using gateway = createTestGateway(mode, booksSubgraph); + const query = /* GraphQL */ ` + query BestsellersQuery { + bestsellers { + title + author { + name + } + publisher { + name + address { + zipCode + } + } } } - } - } - `; - const response = await gateway.fetch('http://localhost:4000/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query }), - }); - const result = await response.json(); - expect(result).toEqual({ - data: { - bestsellers: [book], - }, - extensions: { - cost: { - estimated: 40, - }, - }, - }); - }); - /** - * When requesting 3 books: - * 1 Query (0) + 3 book objects (3 * (1 book object (1) + 1 author object (1) + 1 publisher object (1) + 1 address object (5))) = 24 total cost - * - * When requesting 7 books: - * 1 Query (0) + 3 book objects (7 * (1 book object (1) + 1 author object (1) + 1 publisher object (1) + 1 address object (5))) = 56 total cost - */ - it('@listSize(slicingArguments:)', async () => { - const booksSubgraph = buildSubgraphSchema({ - typeDefs: parse(/* GraphQL */ ` - type Query { - newestAdditions(after: ID, limit: Int!): [Book] - @listSize(slicingArguments: ["limit"]) - } + `; + const response = await gateway.fetch('http://localhost:4000/graphql', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ query }), + }); + const result = await response.json(); + expect(result).toEqual({ + data: { + bestsellers: [book], + }, + extensions: { + cost: { + estimated: 40, + }, + }, + }); + }); + /** + * When requesting 3 books: + * 1 Query (0) + 3 book objects (3 * (1 book object (1) + 1 author object (1) + 1 publisher object (1) + 1 address object (5))) = 24 total cost + * + * When requesting 7 books: + * 1 Query (0) + 3 book objects (7 * (1 book object (1) + 1 author object (1) + 1 publisher object (1) + 1 address object (5))) = 56 total cost + */ + it('@listSize(slicingArguments:)', async () => { + const booksSubgraph = buildSubgraphSchema({ + typeDefs: parse(/* GraphQL */ ` + type Query { + newestAdditions(after: ID, limit: Int!): [Book] + @listSize(slicingArguments: ["limit"]) + } - type Book { - title: String - author: Author - publisher: Publisher - } + type Book { + title: String + author: Author + publisher: Publisher + } - type Author { - name: String - } + type Author { + name: String + } - type Publisher { - name: String - address: Address - } + type Publisher { + name: String + address: Address + } - type Address @cost(weight: 5) { - zipCode: Int! - } - extend schema - @link( - url: "https://specs.apollo.dev/federation/v2.9" - import: ["@cost", "@listSize"] - ) { - query: Query - } - `), - resolvers: { - Query: { - book: (_root, { id }) => { - if (id === '1') { - return book; + type Address @cost(weight: 5) { + zipCode: Int! } - throw new Error('Book not found'); + extend schema + @link( + url: "https://specs.apollo.dev/federation/v2.9" + import: ["@cost", "@listSize"] + ) { + query: Query + } + `), + resolvers: { + Query: { + book: (_root, { id }) => { + if (id === '1') { + return book; + } + throw new Error('Book not found'); + }, + bestsellers: () => [book], + newestAdditions: () => [book], + }, }, - bestsellers: () => [book], - newestAdditions: () => [book], - }, - }, - }); - await using booksServer = createYoga({ - schema: booksSubgraph, - }); - await using gateway = createGatewayRuntime({ - supergraph: await composeLocalSchemasWithApollo([ - { - name: 'books', - schema: booksSubgraph, - url: 'http://books/graphql', - }, - ]), - plugins: () => [ - // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch - useCustomFetch(booksServer.fetch), - useDemandControl({ - includeExtensionMetadata: true, - }), - ], - }); - /* Querying 3 books start */ - const queryWith3 = /* GraphQL */ ` - query NewestAdditions { - newestAdditions(limit: 3) { - title - author { - name - } - publisher { - name - address { - zipCode + }); + await using gateway = createTestGateway(mode, booksSubgraph); + /* Querying 3 books start */ + const queryWith3 = /* GraphQL */ ` + query NewestAdditions { + newestAdditions(limit: 3) { + title + author { + name + } + publisher { + name + address { + zipCode + } + } } } - } - } - `; - const responseWith3 = await gateway.fetch('http://localhost:4000/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query: queryWith3 }), - }); - const resultWith3 = await responseWith3.json(); - expect(resultWith3).toEqual({ - data: { - newestAdditions: [book], - }, - extensions: { - cost: { - estimated: 24, - }, - }, - }); - /* Querying 3 books end */ - /* Querying 7 books start */ - const queryWith7 = /* GraphQL */ ` - query NewestAdditions { - newestAdditions(limit: 7) { - title - author { - name - } - publisher { - name - address { - zipCode + `; + const responseWith3 = await gateway.fetch( + 'http://localhost:4000/graphql', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ query: queryWith3 }), + }, + ); + const resultWith3 = await responseWith3.json(); + expect(resultWith3).toEqual({ + data: { + newestAdditions: [book], + }, + extensions: { + cost: { + estimated: 24, + }, + }, + }); + /* Querying 3 books end */ + /* Querying 7 books start */ + const queryWith7 = /* GraphQL */ ` + query NewestAdditions { + newestAdditions(limit: 7) { + title + author { + name + } + publisher { + name + address { + zipCode + } + } } } - } - } - `; - const responseWith7 = await gateway.fetch('http://localhost:4000/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query: queryWith7 }), - }); - const resultWith7 = await responseWith7.json(); - expect(resultWith7).toEqual({ - data: { - newestAdditions: [book], - }, - extensions: { - cost: { - estimated: 56, - }, - }, - }); - /* Querying 7 books end */ - }); + `; + const responseWith7 = await gateway.fetch( + 'http://localhost:4000/graphql', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ query: queryWith7 }), + }, + ); + const resultWith7 = await responseWith7.json(); + expect(resultWith7).toEqual({ + data: { + newestAdditions: [book], + }, + extensions: { + cost: { + estimated: 56, + }, + }, + }); + /* Querying 7 books end */ + }); - it('"max" option', async () => { - const booksSubgraph = buildSubgraphSchema({ - typeDefs: parse(/* GraphQL */ ` - type Query { - book(id: ID): Book - } + it('"max" option', async () => { + const booksSubgraph = buildSubgraphSchema({ + typeDefs: parse(/* GraphQL */ ` + type Query { + book(id: ID): Book + } - type Book { - title: String - author: Author - publisher: Publisher - } + type Book { + title: String + author: Author + publisher: Publisher + } - type Author { - name: String - } + type Author { + name: String + } - type Publisher { - name: String - address: Address - } + type Publisher { + name: String + address: Address + } - type Address { - zipCode: Int! - } - `), - resolvers: { - Query: { - book: (_root, { id }) => { - if (id === '1') { - return book; + type Address { + zipCode: Int! } - throw new Error('Book not found'); + `), + resolvers: { + Query: { + book: (_root, { id }) => { + if (id === '1') { + return book; + } + throw new Error('Book not found'); + }, + }, }, - }, - }, - }); - await using booksServer = createYoga({ - schema: booksSubgraph, - }); - await using gateway = createGatewayRuntime({ - supergraph: await composeLocalSchemasWithApollo([ - { - name: 'books', - schema: booksSubgraph, - url: 'http://books/graphql', - }, - ]), - plugins: () => [ - // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch - useCustomFetch(booksServer.fetch), - useDemandControl({ - maxCost: 3, - }), - ], - }); - const query = /* GraphQL */ ` - query BookQuery { - book(id: 1) { - title - author { - name - } - publisher { - name - address { - zipCode + }); + await using gateway = createTestGateway( + mode, + booksSubgraph, + { + maxCost: 3, + }, + true, + ); + const query = /* GraphQL */ ` + query BookQuery { + book(id: 1) { + title + author { + name + } + publisher { + name + address { + zipCode + } + } } } - } - } - `; - const response = await gateway.fetch('http://localhost:4000/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query }), - }); - const result = await response.json(); - expect(result).toEqual({ - data: { - book: null, - }, - errors: [ - { - message: 'Operation estimated cost 4 exceeded configured maximum 3', - extensions: { - code: 'COST_ESTIMATED_TOO_EXPENSIVE', - cost: { - estimated: 4, - max: 3, - }, + `; + const response = await gateway.fetch('http://localhost:4000/graphql', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', }, - locations: [ + body: JSON.stringify({ query }), + }); + const result = await response.json(); + expect(result.data?.book).toBeFalsy(); + expect(result).toMatchObject({ + errors: [ { - line: 3, - column: 9, + message: + 'Operation estimated cost 4 exceeded configured maximum 3', + extensions: { + code: 'COST_ESTIMATED_TOO_EXPENSIVE', + cost: { + estimated: 4, + max: 3, + }, + }, }, ], - path: ['book'], - }, - ], - }); - }); + }); + }); - it('"defaultAssumedListSize" option', async () => { - const booksSubgraph = buildSubgraphSchema({ - typeDefs: parse(/* GraphQL */ ` - type Query { - bestsellers: [Book] - } + it('"defaultAssumedListSize" option', async () => { + const booksSubgraph = buildSubgraphSchema({ + typeDefs: parse(/* GraphQL */ ` + type Query { + bestsellers: [Book] + } - type Book { - title: String - author: Author - publisher: Publisher - } + type Book { + title: String + author: Author + publisher: Publisher + } - type Author { - name: String - } + type Author { + name: String + } - type Publisher { - name: String - address: Address - } + type Publisher { + name: String + address: Address + } - type Address @cost(weight: 5) { - zipCode: Int! - } - extend schema - @link( - url: "https://specs.apollo.dev/federation/v2.9" - import: ["@cost"] - ) { - query: Query - } - `), - resolvers: { - Query: { - book: (_root, { id }) => { - if (id === '1') { - return book; + type Address @cost(weight: 5) { + zipCode: Int! + } + extend schema + @link( + url: "https://specs.apollo.dev/federation/v2.9" + import: ["@cost"] + ) { + query: Query } - throw new Error('Book not found'); + `), + resolvers: { + Query: { + book: (_root, { id }) => { + if (id === '1') { + return book; + } + throw new Error('Book not found'); + }, + bestsellers: () => [book], + }, }, - bestsellers: () => [book], - }, - }, - }); - await using booksServer = createYoga({ - schema: booksSubgraph, - }); - await using gateway = createGatewayRuntime({ - supergraph: await composeLocalSchemasWithApollo([ - { - name: 'books', - schema: booksSubgraph, - url: 'http://books/graphql', - }, - ]), - plugins: () => [ - // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch - useCustomFetch(booksServer.fetch), - useDemandControl({ + }); + await using gateway = createTestGateway(mode, booksSubgraph, { includeExtensionMetadata: true, listSize: 5, - }), - ], - }); - const query = /* GraphQL */ ` - query BestsellersQuery { - bestsellers { - title - author { - name - } - publisher { - name - address { - zipCode + }); + const query = /* GraphQL */ ` + query BestsellersQuery { + bestsellers { + title + author { + name + } + publisher { + name + address { + zipCode + } + } } } - } - } - `; - const response = await gateway.fetch('http://localhost:4000/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query }), - }); - const result = await response.json(); - expect(result).toEqual({ - data: { - bestsellers: [book], - }, - extensions: { - cost: { - estimated: 40, - }, - }, - }); - }); + `; + const response = await gateway.fetch('http://localhost:4000/graphql', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ query }), + }); + const result = await response.json(); + expect(result).toEqual({ + data: { + bestsellers: [book], + }, + extensions: { + cost: { + estimated: 40, + }, + }, + }); + }); - it('@listSize(slicingArguments:, requireOneSlicingArgument:true)', async () => { - const itemsSubgraph = buildSubgraphSchema({ - typeDefs: parse(/* GraphQL */ ` - extend schema - @link( - url: "https://specs.apollo.dev/federation/v2.9" - import: ["@listSize"] - ) { - query: Query - } + it('@listSize(slicingArguments:, requireOneSlicingArgument:true)', async () => { + const itemsSubgraph = buildSubgraphSchema({ + typeDefs: parse(/* GraphQL */ ` + extend schema + @link( + url: "https://specs.apollo.dev/federation/v2.9" + import: ["@listSize"] + ) { + query: Query + } - type Query { - items(first: Int, last: Int): [Item!] - @listSize(slicingArguments: ["first", "last"]) - } + type Query { + items(first: Int, last: Int): [Item!] + @listSize(slicingArguments: ["first", "last"]) + } - type Item { - id: ID - } - `), - resolvers: { - Query: { - items: () => [{ id: 'Item 1' }, { id: 'Item 2' }], - }, - }, - }); - await using itemsServer = createYoga({ - schema: itemsSubgraph, - }); - await using gateway = createGatewayRuntime({ - supergraph: await composeLocalSchemasWithApollo([ - { - name: 'items', + type Item { + id: ID + } + `), + resolvers: { + Query: { + items: () => [{ id: 'Item 1' }, { id: 'Item 2' }], + }, + }, + }); + await using itemsServer = createYoga({ schema: itemsSubgraph, - url: 'http://items/graphql', - }, - ]), - plugins: () => [ - // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch - useCustomFetch(itemsServer.fetch), - useDemandControl({ - includeExtensionMetadata: true, - }), - ], - }); - const query = /* GraphQL */ ` - query ItemsQuery { - items(first: 2, last: 3) { - id - } - } - `; - const response = await gateway.fetch('http://localhost:4000/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query }), - }); - const result = await response.json(); - expect(result).toEqual({ - data: { - items: null, - }, - errors: [ - { - message: - 'Only one slicing argument is allowed on field "items"; found multiple slicing arguments "first, last"', - extensions: { - code: 'COST_QUERY_PARSE_FAILURE', + }); + await using gateway = createGatewayRuntime({ + supergraph: await composeLocalSchemasWithApollo([ + { + name: 'items', + schema: itemsSubgraph, + url: 'http://items/graphql', + }, + ]), + plugins: () => [ + // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch + useCustomFetch(itemsServer.fetch), + useDemandControl({ + includeExtensionMetadata: true, + }), + ], + }); + const query = /* GraphQL */ ` + query ItemsQuery { + items(first: 2, last: 3) { + id + } + } + `; + const response = await gateway.fetch('http://localhost:4000/graphql', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ query }), + }); + const result = await response.json(); + expect(result).toEqual({ + data: { + items: null, }, - locations: [ + errors: [ { - line: 3, - column: 9, + message: + 'Only one slicing argument is allowed on field "items"; found multiple slicing arguments "first, last"', + extensions: { + code: 'COST_QUERY_PARSE_FAILURE', + }, + locations: [ + { + line: 3, + column: 13, + }, + ], + path: ['items'], }, ], - path: ['items'], - }, - ], - extensions: { - cost: { - estimated: 0, - }, - }, - }); - }); - it('@listSize(slicingArguments:, requireOneSlicingArgument:false)', async () => { - const itemsSubgraph = buildSubgraphSchema({ - typeDefs: parse(/* GraphQL */ ` - extend schema - @link( - url: "https://specs.apollo.dev/federation/v2.9" - import: ["@listSize"] - ) { - query: Query - } + extensions: { + cost: { + estimated: 0, + }, + }, + }); + }); + it('@listSize(slicingArguments:, requireOneSlicingArgument:false)', async () => { + const itemsSubgraph = buildSubgraphSchema({ + typeDefs: parse(/* GraphQL */ ` + extend schema + @link( + url: "https://specs.apollo.dev/federation/v2.9" + import: ["@listSize"] + ) { + query: Query + } - type Query { - items(first: Int, last: Int): [Item!] - @listSize( - slicingArguments: ["first", "last"] - requireOneSlicingArgument: false - ) - } + type Query { + items(first: Int, last: Int): [Item!] + @listSize( + slicingArguments: ["first", "last"] + requireOneSlicingArgument: false + ) + } - type Item { - id: ID - } - `), - resolvers: { - Query: { - items: () => [{ id: 'Item 1' }, { id: 'Item 2' }], - }, - }, - }); - await using itemsServer = createYoga({ - schema: itemsSubgraph, - }); - await using gateway = createGatewayRuntime({ - supergraph: await composeLocalSchemasWithApollo([ - { - name: 'items', + type Item { + id: ID + } + `), + resolvers: { + Query: { + items: () => [{ id: 'Item 1' }, { id: 'Item 2' }], + }, + }, + }); + await using itemsServer = createYoga({ schema: itemsSubgraph, - url: 'http://items/graphql', - }, - ]), - plugins: () => [ - // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch - useCustomFetch(itemsServer.fetch), - useDemandControl({ - includeExtensionMetadata: true, - }), - ], - }); - const query = /* GraphQL */ ` - query ItemsQuery { - items(first: 2, last: 3) { - id - } - } - `; - const response = await gateway.fetch('http://localhost:4000/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query }), - }); - const result = await response.json(); - expect(result).toEqual({ - data: { - items: [{ id: 'Item 1' }, { id: 'Item 2' }], - }, - extensions: { - cost: { - estimated: 3, - }, - }, - }); - }); - it('@listSize(sizedFields:)', async () => { - const itemsSubgraph = buildSubgraphSchema({ - typeDefs: parse(/* GraphQL */ ` - extend schema - @link( - url: "https://specs.apollo.dev/federation/v2.9" - import: ["@listSize"] - ) { - query: Query - } + }); + await using gateway = createGatewayRuntime({ + supergraph: await composeLocalSchemasWithApollo([ + { + name: 'items', + schema: itemsSubgraph, + url: 'http://items/graphql', + }, + ]), + plugins: () => [ + // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch + useCustomFetch(itemsServer.fetch), + useDemandControl({ + includeExtensionMetadata: true, + }), + ], + }); + const query = /* GraphQL */ ` + query ItemsQuery { + items(first: 2, last: 3) { + id + } + } + `; + const response = await gateway.fetch('http://localhost:4000/graphql', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ query }), + }); + const result = await response.json(); + expect(result).toEqual({ + data: { + items: [{ id: 'Item 1' }, { id: 'Item 2' }], + }, + extensions: { + cost: { + estimated: 3, + }, + }, + }); + }); + it('@listSize(sizedFields:)', async () => { + const itemsSubgraph = buildSubgraphSchema({ + typeDefs: parse(/* GraphQL */ ` + extend schema + @link( + url: "https://specs.apollo.dev/federation/v2.9" + import: ["@listSize"] + ) { + query: Query + } - type Query { - items(first: Int): Cursor! - @listSize(slicingArguments: ["first"], sizedFields: ["page"]) - } + type Query { + items(first: Int): Cursor! + @listSize(slicingArguments: ["first"], sizedFields: ["page"]) + } - type Cursor { - page: [Item!] - nextPageToken: String - } + type Cursor { + page: [Item!] + nextPageToken: String + } - type Item { - id: ID - } - `), - resolvers: { - Query: { - items: () => ({ - page: [{ id: 'Item 1' }, { id: 'Item 2' }], - nextPageToken: 'token', - }), - }, - }, - }); - await using itemsServer = createYoga({ - schema: itemsSubgraph, - }); - await using gateway = createGatewayRuntime({ - supergraph: await composeLocalSchemasWithApollo([ - { - name: 'items', + type Item { + id: ID + } + `), + resolvers: { + Query: { + items: () => ({ + page: [{ id: 'Item 1' }, { id: 'Item 2' }], + nextPageToken: 'token', + }), + }, + }, + }); + await using itemsServer = createYoga({ schema: itemsSubgraph, - url: 'http://items/graphql', - }, - ]), - plugins: () => [ - // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch - useCustomFetch(itemsServer.fetch), - useDemandControl({ - includeExtensionMetadata: true, - }), - ], - }); - const query = /* GraphQL */ ` - query ItemsQuery { - items(first: 5) { - page { - id + }); + await using gateway = createGatewayRuntime({ + supergraph: await composeLocalSchemasWithApollo([ + { + name: 'items', + schema: itemsSubgraph, + url: 'http://items/graphql', + }, + ]), + plugins: () => [ + // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch + useCustomFetch(itemsServer.fetch), + useDemandControl({ + includeExtensionMetadata: true, + }), + ], + }); + const query = /* GraphQL */ ` + query ItemsQuery { + items(first: 5) { + page { + id + } + nextPageToken + } } - nextPageToken - } - } - `; - const response = await gateway.fetch('http://localhost:4000/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query }), - }); - const result = await response.json(); - expect(result).toEqual({ - data: { - items: { - page: [{ id: 'Item 1' }, { id: 'Item 2' }], - nextPageToken: 'token', - }, - }, - extensions: { - cost: { - estimated: 6, - }, - }, - }); - }); + `; + const response = await gateway.fetch('http://localhost:4000/graphql', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ query }), + }); + const result = await response.json(); + expect(result).toEqual({ + data: { + items: { + page: [{ id: 'Item 1' }, { id: 'Item 2' }], + nextPageToken: 'token', + }, + }, + extensions: { + cost: { + estimated: 6, + }, + }, + }); + }); - /** - * 1 Query (0) + 1 book object (1) + 1 author object (1) + 1 publisher object (1) + 1 address object (5) = 8 total cost - */ - it('@cost in object but aliased as @myCost', async () => { - const booksSubgraph = buildSubgraphSchema({ - typeDefs: parse(/* GraphQL */ ` - type Query { - book(id: ID): Book - } + /** + * 1 Query (0) + 1 book object (1) + 1 author object (1) + 1 publisher object (1) + 1 address object (5) = 8 total cost + */ + // Skipped in proxy mode because the proxy does not support custom directive aliasing (e.g., @cost as @myCost). + it.skipIf(mode === 'proxy')( + '@cost in object but aliased as @myCost', + async () => { + const booksSubgraph = buildSubgraphSchema({ + typeDefs: parse(/* GraphQL */ ` + type Query { + book(id: ID): Book + } - type Book { - title: String - author: Author - publisher: Publisher - } + type Book { + title: String + author: Author + publisher: Publisher + } - type Author { - name: String - } + type Author { + name: String + } - type Publisher { - name: String - address: Address - } + type Publisher { + name: String + address: Address + } - type Address @myCost(weight: 5) { - zipCode: Int! - } - extend schema - @link( - url: "https://specs.apollo.dev/federation/v2.9" - import: [{ name: "@cost", as: "@myCost" }] - ) { - query: Query - } - `), - resolvers: { - Query: { - book: (_root, { id }) => { - if (id === '1') { - return book; - } - throw new Error('Book not found'); - }, - }, - }, - }); - await using booksServer = createYoga({ - schema: booksSubgraph, - }); - await using gateway = createGatewayRuntime({ - supergraph: await composeLocalSchemasWithApollo([ - { - name: 'books', - schema: booksSubgraph, - url: 'http://books/graphql', - }, - ]), - plugins: () => [ - // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch - useCustomFetch(booksServer.fetch), - useDemandControl({ - includeExtensionMetadata: true, - }), - ], - }); - const query = /* GraphQL */ ` - query BookQuery { - book(id: 1) { - title - author { - name - } - publisher { - name - address { - zipCode + type Address @myCost(weight: 5) { + zipCode: Int! + } + extend schema + @link( + url: "https://specs.apollo.dev/federation/v2.9" + import: [{ name: "@cost", as: "@myCost" }] + ) { + query: Query + } + `), + resolvers: { + Query: { + book: (_root, { id }) => { + if (id === '1') { + return book; + } + throw new Error('Book not found'); + }, + }, + }, + }); + await using gateway = createTestGateway(mode, booksSubgraph); + const query = /* GraphQL */ ` + query BookQuery { + book(id: 1) { + title + author { + name + } + publisher { + name + address { + zipCode + } + } + } } - } - } - } - `; - const response = await gateway.fetch('http://localhost:4000/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query }), - }); - const result = await response.json(); - expect(result).toEqual({ - data: { - book, - }, - extensions: { - cost: { - estimated: 8, + `; + const response = await gateway.fetch( + 'http://localhost:4000/graphql', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ query }), + }, + ); + const result = await response.json(); + expect(result).toEqual({ + data: { + book, + }, + extensions: { + cost: { + estimated: 8, + }, + }, + }); }, - }, - }); - }); + ); - it('returns cost even if it does not hit the subgraph', async () => { - const subgraph = buildSubgraphSchema({ - typeDefs: parse(/* GraphQL */ ` - type Query { - foo: String - } - `), - }); - await using subgraphServer = createYoga({ - schema: subgraph, - }); - await using gateway = createGatewayRuntime({ - supergraph: await composeLocalSchemasWithApollo([ - { - name: 'subgraph', + it('returns cost even if it does not hit the subgraph', async () => { + const subgraph = buildSubgraphSchema({ + typeDefs: parse(/* GraphQL */ ` + type Query { + foo: String + } + `), + }); + await using subgraphServer = createYoga({ schema: subgraph, - url: 'http://subgraph/graphql', - }, - ]), - plugins: () => [ - // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch - useCustomFetch(subgraphServer.fetch), - useDemandControl({ - includeExtensionMetadata: true, - }), - ], - }); - const query = /* GraphQL */ ` - query EmptyQuery { - __typename - a: __typename - } - `; - const response = await gateway.fetch('http://localhost:4000/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query }), - }); - const result = await response.json(); - expect(result).toEqual({ - data: { - __typename: 'Query', - a: 'Query', - }, - extensions: { - cost: { - estimated: 0, - }, - }, - }); - }); + }); + await using gateway = createGatewayRuntime({ + supergraph: await composeLocalSchemasWithApollo([ + { + name: 'subgraph', + schema: subgraph, + url: 'http://subgraph/graphql', + }, + ]), + plugins: () => [ + // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch + useCustomFetch(subgraphServer.fetch), + useDemandControl({ + includeExtensionMetadata: true, + }), + ], + }); + const query = /* GraphQL */ ` + query EmptyQuery { + __typename + a: __typename + } + `; + const response = await gateway.fetch('http://localhost:4000/graphql', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ query }), + }); + const result = await response.json(); + expect(result).toEqual({ + data: { + __typename: 'Query', + a: 'Query', + }, + extensions: { + cost: { + estimated: 0, + }, + }, + }); + }); - it('handles batched requests', async () => { - const subgraph = buildSubgraphSchema({ - typeDefs: parse(/* GraphQL */ ` - type Query { - foo: Foo - bar: Bar - } + it('handles batched requests', async () => { + const subgraph = buildSubgraphSchema({ + typeDefs: parse(/* GraphQL */ ` + type Query { + foo: Foo + bar: Bar + } - type Foo { - id: ID - } + type Foo { + id: ID + } - type Bar { - id: ID - } - `), - resolvers: { - Query: { - foo: async () => ({ id: 'foo' }), - bar: async () => ({ id: 'bar' }), - }, - }, - }); - await using subgraphServer = createYoga({ - schema: subgraph, - }); - await using gateway = createGatewayRuntime({ - supergraph: await composeLocalSchemasWithApollo([ - { - name: 'subgraph', + type Bar { + id: ID + } + `), + resolvers: { + Query: { + foo: async () => ({ id: 'foo' }), + bar: async () => ({ id: 'bar' }), + }, + }, + }); + await using subgraphServer = createYoga({ schema: subgraph, - url: 'http://subgraph/graphql', - }, - ]), - plugins: () => [ - // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch - useCustomFetch(subgraphServer.fetch), - useDemandControl({ - includeExtensionMetadata: true, - maxCost: 1, - }), - ], - }); - const query = /* GraphQL */ ` - query FooQuery { - foo { - id - } - bar { - id - } - } - `; - const response = await gateway.fetch('http://localhost:4000/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query }), - }); - const result = await response.json(); - expect(result).toEqual({ - data: { - foo: null, - bar: null, - }, - errors: [ - { - extensions: { - code: 'COST_ESTIMATED_TOO_EXPENSIVE', - cost: { - estimated: 2, - max: 1, + }); + await using gateway = createGatewayRuntime({ + supergraph: await composeLocalSchemasWithApollo([ + { + name: 'subgraph', + schema: subgraph, + url: 'http://subgraph/graphql', }, + ]), + plugins: () => [ + // @ts-expect-error TODO: MeshFetch is not compatible with @whatwg-node/server fetch + useCustomFetch(subgraphServer.fetch), + useDemandControl({ + includeExtensionMetadata: true, + maxCost: 1, + }), + ], + }); + const query = /* GraphQL */ ` + query FooQuery { + foo { + id + } + bar { + id + } + } + `; + const response = await gateway.fetch('http://localhost:4000/graphql', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ query }), + }); + const result = await response.json(); + expect(result).toEqual({ + data: { + foo: null, + bar: null, }, - locations: [ + errors: [ + { + extensions: { + code: 'COST_ESTIMATED_TOO_EXPENSIVE', + cost: { + estimated: 2, + max: 1, + }, + }, + locations: [ + { + column: 13, + line: 3, + }, + ], + message: + 'Operation estimated cost 2 exceeded configured maximum 1', + path: ['foo'], + }, { - column: 9, - line: 3, + extensions: { + code: 'COST_ESTIMATED_TOO_EXPENSIVE', + cost: { + estimated: 2, + max: 1, + }, + }, + locations: [ + { + column: 13, + line: 6, + }, + ], + message: + 'Operation estimated cost 2 exceeded configured maximum 1', + path: ['bar'], }, ], - message: 'Operation estimated cost 2 exceeded configured maximum 1', - path: ['foo'], - }, - { extensions: { - code: 'COST_ESTIMATED_TOO_EXPENSIVE', cost: { estimated: 2, max: 1, }, }, - locations: [ - { - column: 9, - line: 6, - }, - ], - message: 'Operation estimated cost 2 exceeded configured maximum 1', - path: ['bar'], - }, - ], - extensions: { - cost: { - estimated: 2, - max: 1, - }, - }, + }); + }); }); }); });