├── .changeset ├── @graphql-hive_gateway-runtime-1195-dependencies.md ├── @graphql-hive_plugin-aws-sigv4-1195-dependencies.md ├── @graphql-hive_plugin-aws-sigv4-1203-dependencies.md └── config.json ├── .github ├── dependabot.yml └── workflows │ ├── bench.yml │ ├── check.yml │ ├── examples.yml │ ├── memtest.yml │ ├── release.yml │ └── test.yml ├── .gitignore ├── .node-version ├── .npmrc ├── .nvmrc ├── .prettierignore ├── .prettierrc.yml ├── .vscode └── settings.json ├── .yarn ├── custom-plugins │ └── snapshot-no-semver-range.cjs ├── patches │ ├── @changesets-cli-npm-2.27.9-5df61a909e.patch │ ├── @opentelemetry-exporter-trace-otlp-http-npm-0.56.0-dddd282e41.patch │ ├── @opentelemetry-otlp-exporter-base-npm-0.56.0-ba3dc5f5c5.patch │ ├── @opentelemetry-resources-npm-1.29.0-112f89f0c5.patch │ ├── @vitest-snapshot-npm-3.1.1-4d18cf86dc.patch │ ├── ioredis-mock-npm-8.9.0-530d4422b9.patch │ ├── jest-leak-detector+29.7.0.patch │ ├── pkgroll-npm-2.5.1-9b062c22ca.patch │ ├── tsx-npm-4.19.2-a8f2312a2f.patch │ └── vite-tsconfig-paths-npm-5.1.3-1736ca1872.patch └── releases │ └── yarn-4.9.1.cjs ├── .yarnrc.yml ├── DEPS_RESOLUTIONS_NOTES.md ├── LICENSE.md ├── README.md ├── babel.config.cjs ├── bench └── federation │ ├── federation.bench.ts │ └── monolith.ts ├── docker-bake.hcl ├── e2e ├── apq-subgraphs │ ├── apq-subgraphs.e2e.ts │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── package.json │ └── services │ │ └── greetings.ts ├── armor-options │ ├── __snapshots__ │ │ └── armor-options.e2e.ts.snap │ ├── armor-options.e2e.ts │ ├── gateway.config.ts │ └── package.json ├── auto-type-merging │ ├── auto-type-merging.e2e.ts │ ├── auto-type-merging.memtest.ts │ ├── mesh.config.ts │ ├── package.json │ └── services │ │ └── vaccination.ts ├── aws-sigv4 │ ├── aws-sigv4.e2e.ts │ ├── gateway.config.ts │ ├── package.json │ └── services │ │ └── upstream.ts ├── cloudflare-workers │ ├── .gitignore │ ├── cloudflare-workers.e2e.ts │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ └── wrangler.toml ├── config-syntax-error │ ├── config-syntax-error.e2e.ts │ ├── custom-resolvers.ts │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── package.json │ └── services │ │ └── hello.ts ├── demand-control │ ├── demand-control.e2e.ts │ ├── gateway.config.ts │ ├── package.json │ └── services │ │ └── books.ts ├── extra-fields │ ├── extra-fields.e2e.ts │ ├── mesh.config.ts │ ├── package.json │ └── services │ │ ├── bar.ts │ │ └── foo.ts ├── federation-batching-plan │ ├── federation-batching-plan.e2e.ts │ ├── gateway.config.ts │ └── package.json ├── federation-example │ ├── federation-example.bench.ts │ ├── federation-example.e2e.ts │ ├── federation-example.memtest.ts │ ├── package.json │ └── services │ │ └── apollo-gateway.ts ├── federation-mixed │ ├── federation-mixed.e2e.ts │ ├── federation-mixed.memtest.ts │ ├── mesh.config.ts │ ├── package.json │ └── services │ │ └── accounts │ │ ├── index.ts │ │ └── server.ts ├── federation-rate-limiting │ ├── federation-rate-limiting.e2e.ts │ ├── gateway.config.ts │ └── package.json ├── federation-subscriptions-passthrough │ ├── federation-subscriptions-passthrough.e2e.ts │ ├── federation-subscriptions-passthrough.memtest.ts │ ├── gateway.config.ts │ ├── package.json │ └── services │ │ ├── products │ │ ├── index.ts │ │ ├── server.ts │ │ └── typeDefs.graphql │ │ └── reviews │ │ ├── index.ts │ │ ├── server.ts │ │ └── typeDefs.graphql ├── file-upload │ ├── file-upload.e2e.ts │ ├── mesh.config.ts │ ├── package.json │ └── services │ │ └── bucket.ts ├── graceful-shutdown │ ├── graceful-shutdown.e2e.ts │ └── package.json ├── graphos-polling │ ├── graphos-polling.e2e.ts │ ├── package.json │ └── services │ │ ├── gateway-fastify.ts │ │ ├── graphos.ts │ │ ├── upstream_good.ts │ │ └── upstream_stuck.ts ├── graphos │ ├── .gitignore │ ├── graphos.e2e.ts │ └── package.json ├── header-propagation │ ├── gateway.config.ts │ ├── header-propagation.e2e.ts │ ├── package.json │ └── services │ │ └── upstream.ts ├── hmac-auth-https │ ├── README.md │ ├── gateway.config.ts │ ├── hmac-auth-https.e2e.ts │ ├── mesh.config.ts │ ├── package.json │ └── services │ │ ├── comments │ │ ├── index.ts │ │ └── typeDefs.graphql │ │ └── users │ │ ├── index.ts │ │ └── typeDefs.graphql ├── hoist-and-prefix-transform │ ├── hoist-and-prefix-transform.e2e.ts │ ├── mesh.config.ts │ ├── package.json │ └── services │ │ └── weather.ts ├── interface-additional-resolvers │ ├── additionalTypeDefs │ │ ├── Node.graphql │ │ └── User.ts │ ├── gateway.config.ts │ ├── interface-additional-resolvers.e2e.ts │ ├── interface-additional-resolvers.memtest.ts │ ├── mesh.config.ts │ ├── package.json │ └── services │ │ └── Test.ts ├── js-config │ ├── gateway.config.js │ ├── js-config.e2e.ts │ ├── mesh.config.js │ └── package.json ├── json-schema-subscriptions │ ├── addTodo.json │ ├── gateway.config.ts │ ├── json-schema-subscriptions.e2e.ts │ ├── mesh.config.ts │ ├── package.json │ ├── services │ │ └── api.ts │ ├── todo.json │ └── todos.json ├── manual-transport-def │ ├── gateway.config.ts │ ├── manual-transport-def.e2e.ts │ ├── mesh.config.ts │ ├── package.json │ └── services │ │ ├── greetings.ts │ │ └── helloer.ts ├── naming-convention-additional-typedefs │ ├── __snapshots__ │ │ └── naming-convention-additional-typedefs.e2e.ts.snap │ ├── mesh.config.ts │ ├── naming-convention-additional-typedefs.e2e.ts │ ├── package.json │ └── services │ │ ├── authors.ts │ │ ├── books.ts │ │ └── data.ts ├── nestjs │ ├── nestjs.e2e.ts │ ├── package.json │ └── services │ │ └── nestjs │ │ ├── app.module.ts │ │ └── index.ts ├── openapi-additional-resolvers │ ├── additionalTypeDefs │ │ ├── apple.graphql │ │ └── banana.graphql │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── openapi-additional-resolvers.e2e.ts │ └── package.json ├── openapi-arg-rename │ ├── mesh.config.ts │ ├── openapi-arg-rename.e2e.ts │ ├── openapi.json │ ├── package.json │ └── services │ │ └── Wiki.ts ├── openapi-javascript-wiki │ ├── gateway.Dockerfile │ ├── gateway.config.ts │ ├── gateway_bun.Dockerfile │ ├── mesh.config.ts │ ├── openapi-javascript-wiki.e2e.ts │ └── package.json ├── openapi-min-length │ ├── mesh.config.ts │ ├── openapi-min-length.e2e.ts │ ├── openapi.json │ └── package.json ├── openapi-naming-convention │ ├── mesh.config.ts │ ├── openapi-naming-convention.e2e.ts │ ├── openapi.json │ └── package.json ├── openapi-prune │ ├── mesh.config.ts │ ├── openapi-prune.e2e.ts │ ├── openapi.json │ ├── package.json │ └── services │ │ └── Wiki.ts ├── openapi-subgraph │ ├── mesh.config.ts │ ├── openapi-subgraph.e2e.ts │ ├── package.json │ └── services │ │ ├── GQL.ts │ │ └── OAS.ts ├── openapi-subscriptions │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── openapi-subscriptions.e2e.ts │ ├── package.json │ └── services │ │ └── api │ │ ├── index.ts │ │ └── openapi.yml ├── opentelemetry │ ├── gateway.config.ts │ ├── opentelemetry.e2e.ts │ ├── opentelemetry.memtest.ts │ └── package.json ├── operation-field-permissions │ ├── gateway.Dockerfile │ ├── gateway.config.ts │ ├── gateway_bun.Dockerfile │ ├── mesh.config.ts │ ├── operation-field-permissions.e2e.ts │ ├── package.json │ └── services │ │ └── users.ts ├── polling │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── package.json │ ├── polling.e2e.ts │ └── services │ │ ├── Graph.graphql │ │ └── Graph.ts ├── programmatic-batching │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── package.json │ ├── programmatic-batching.e2e.ts │ ├── programmatic-batching.memtest.ts │ └── services │ │ └── api.ts ├── regular-subgraph │ ├── mesh.config.ts │ ├── package.json │ ├── regular-subgraph.e2e.ts │ └── services │ │ └── regular.ts ├── retry-timeout │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── package.json │ ├── retry-timeout.e2e.ts │ └── services │ │ ├── gql-flakey.ts │ │ └── oai-flakey.ts ├── self-hosting-hive │ ├── gateway.config.ts │ ├── package.json │ ├── self-hosting-hive.e2e.ts │ └── services │ │ └── selfHostingHive.ts ├── subscriptions-cancellation │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── package.json │ ├── services │ │ └── stream.ts │ └── subscriptions-cancellation.e2e.ts ├── subscriptions-data-other-subgraph │ ├── package.json │ ├── services │ │ ├── posts.ts │ │ └── users.ts │ └── subscriptions-data-other-subgraph.e2e.ts ├── subscriptions-with-transforms │ ├── mesh.config.ts │ ├── package.json │ ├── services │ │ └── my-subgraph │ │ │ ├── index.ts │ │ │ └── schema.graphql │ └── subscriptions-with-transforms.e2e.ts ├── supergraph-file-watcher │ ├── mesh.config.ts │ ├── package.json │ ├── services │ │ ├── a.ts │ │ └── b.ts │ └── supergraph-file-watcher.e2e.ts ├── supergraph-url │ ├── package.json │ ├── services │ │ └── cdn.ts │ └── supergraph-url.e2e.ts ├── top-level-await │ ├── gateway.config.mjs │ ├── package.json │ └── top-level-await.e2e.ts ├── tsconfig-paths │ ├── folder │ │ └── hck.ts │ ├── gateway.config.ts │ ├── tsconfig-paths.e2e.ts │ └── tsconfig-paths.tsconfig.json └── type-merging-batching │ ├── __snapshots__ │ └── type-merging-batching.e2e.ts.snap │ ├── mesh.config.ts │ ├── package.json │ ├── services │ ├── authors.ts │ └── books.ts │ └── type-merging-batching.e2e.ts ├── eslint.config.js ├── examples ├── README.md ├── apq-subgraphs │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── example.tar.gz │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── package-lock.json │ ├── package.json │ └── services │ │ └── greetings.ts ├── extra-fields │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── example.tar.gz │ ├── mesh.config.ts │ ├── package-lock.json │ ├── package.json │ └── services │ │ ├── bar.ts │ │ └── foo.ts ├── federation-example │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── example.tar.gz │ ├── federation-example.bench.ts │ ├── package-lock.json │ ├── package.json │ ├── services │ │ ├── accounts │ │ │ ├── index.ts │ │ │ ├── server.ts │ │ │ └── typeDefs.graphql │ │ ├── inventory │ │ │ ├── index.ts │ │ │ ├── server.ts │ │ │ └── typeDefs.graphql │ │ ├── products │ │ │ ├── index.ts │ │ │ ├── server.ts │ │ │ └── typeDefs.graphql │ │ └── reviews │ │ │ ├── index.ts │ │ │ ├── server.ts │ │ │ └── typeDefs.graphql │ └── supergraph.json ├── federation-mixed │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── example.tar.gz │ ├── mesh.config.ts │ ├── package-lock.json │ ├── package.json │ └── services │ │ ├── accounts │ │ ├── index.ts │ │ └── server.ts │ │ ├── inventory │ │ ├── index.ts │ │ ├── server.ts │ │ └── typeDefs.graphql │ │ ├── products │ │ ├── index.ts │ │ ├── server.ts │ │ └── typeDefs.graphql │ │ └── reviews │ │ ├── index.ts │ │ ├── server.ts │ │ └── typeDefs.graphql ├── federation-subscriptions-passthrough │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── example.tar.gz │ ├── gateway.config.ts │ ├── package-lock.json │ ├── package.json │ ├── services │ │ ├── products │ │ │ ├── index.ts │ │ │ ├── server.ts │ │ │ └── typeDefs.graphql │ │ └── reviews │ │ │ ├── index.ts │ │ │ ├── server.ts │ │ │ └── typeDefs.graphql │ └── supergraph.json ├── file-upload │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── example.tar.gz │ ├── mesh.config.ts │ ├── package-lock.json │ ├── package.json │ └── services │ │ └── bucket.ts ├── hmac-auth-https │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── example.tar.gz │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── package-lock.json │ ├── package.json │ └── services │ │ ├── comments │ │ ├── index.ts │ │ └── typeDefs.graphql │ │ └── users │ │ ├── index.ts │ │ └── typeDefs.graphql ├── interface-additional-resolvers │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── additionalTypeDefs │ │ ├── Node.graphql │ │ └── User.ts │ ├── example.tar.gz │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── package-lock.json │ ├── package.json │ └── services │ │ └── Test.ts ├── json-schema-subscriptions │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── addTodo.json │ ├── example.tar.gz │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── package-lock.json │ ├── package.json │ ├── services │ │ └── api.ts │ ├── todo.json │ └── todos.json ├── openapi-additional-resolvers │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── additionalTypeDefs │ │ ├── apple.graphql │ │ └── banana.graphql │ ├── example.tar.gz │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── package-lock.json │ └── package.json ├── openapi-arg-rename │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── example.tar.gz │ ├── mesh.config.ts │ ├── openapi.json │ ├── package-lock.json │ ├── package.json │ └── services │ │ └── Wiki.ts ├── openapi-javascript-wiki │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── example.tar.gz │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── package-lock.json │ └── package.json ├── openapi-subscriptions │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── example.tar.gz │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── package-lock.json │ ├── package.json │ └── services │ │ └── api │ │ ├── index.ts │ │ └── openapi.yml ├── operation-field-permissions │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── example.tar.gz │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── package-lock.json │ ├── package.json │ └── services │ │ └── users.ts ├── programmatic-batching │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── example.tar.gz │ ├── gateway.config.ts │ ├── mesh.config.ts │ ├── package-lock.json │ ├── package.json │ └── services │ │ └── api.ts ├── subscriptions-with-transforms │ ├── .codesandbox │ │ └── tasks.json │ ├── .devcontainer │ │ └── devcontainer.json │ ├── README.md │ ├── example.tar.gz │ ├── mesh.config.ts │ ├── package-lock.json │ ├── package.json │ └── services │ │ └── my-subgraph │ │ ├── index.ts │ │ └── schema.graphql └── type-merging-batching │ ├── .codesandbox │ └── tasks.json │ ├── .devcontainer │ └── devcontainer.json │ ├── README.md │ ├── example.tar.gz │ ├── mesh.config.ts │ ├── package-lock.json │ ├── package.json │ └── services │ ├── authors.ts │ └── books.ts ├── internal ├── e2e │ ├── package.json │ └── src │ │ ├── example-setup.ts │ │ ├── index.ts │ │ ├── leftoverStack.ts │ │ ├── services │ │ ├── accounts │ │ │ ├── index.ts │ │ │ ├── server.ts │ │ │ └── typeDefs.graphql │ │ ├── index.ts │ │ ├── inventory │ │ │ ├── index.ts │ │ │ ├── server.ts │ │ │ └── typeDefs.graphql │ │ ├── products │ │ │ ├── index.ts │ │ │ ├── server.ts │ │ │ └── typeDefs.graphql │ │ └── reviews │ │ │ ├── index.ts │ │ │ ├── server.ts │ │ │ └── typeDefs.graphql │ │ ├── tenv.ts │ │ └── timeout.ts ├── examples │ ├── package.json │ ├── src │ │ ├── bin.ts │ │ ├── convert.ts │ │ ├── index.ts │ │ ├── parser.ts │ │ └── utils.ts │ └── tests │ │ └── convert.test.ts ├── perf │ ├── package.json │ ├── speedscope-1.23.0-alpha.4.tgz │ └── src │ │ ├── chart.ts │ │ ├── heap.ts │ │ ├── index.ts │ │ ├── inspector.ts │ │ ├── loadtest-script.ts │ │ ├── loadtest.ts │ │ └── memtest.ts ├── proc │ ├── package.json │ └── src │ │ └── index.ts └── testing │ ├── fixtures │ └── schemas.ts │ ├── package.json │ ├── src │ ├── assertions.ts │ ├── benchConfig.ts │ ├── composeLocalSchemasWithApollo.ts │ ├── env.ts │ ├── getLocalhost.ts │ ├── graphql.ts │ ├── index.ts │ ├── opts.test.ts │ ├── opts.ts │ ├── server.ts │ ├── to-be-similar-gql-doc.ts │ ├── to-be-similar-string.ts │ ├── trimError.ts │ └── vitest.ts │ └── tests │ └── leak-detector.test.ts ├── jest.config.ts ├── package.json ├── packages ├── batch-delegate │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── batchDelegateToSchema.ts │ │ ├── createBatchDelegateFn.ts │ │ ├── getLoader.ts │ │ ├── index.ts │ │ └── types.ts │ └── tests │ │ ├── basic.example.test.ts │ │ ├── cacheByArguments.test.ts │ │ ├── typeMerging.example.test.ts │ │ └── withTransforms.test.ts ├── batch-execute │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── createBatchingExecutor.ts │ │ ├── getBatchingExecutor.ts │ │ ├── index.ts │ │ ├── mergeRequests.ts │ │ ├── prefix.ts │ │ └── splitResult.ts │ └── tests │ │ └── batchExecute.test.ts ├── delegate │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── Subschema.ts │ │ ├── Transformer.ts │ │ ├── applySchemaTransforms.ts │ │ ├── checkResultAndHandleErrors.ts │ │ ├── createRequest.ts │ │ ├── defaultMergedResolver.ts │ │ ├── delegateToSchema.ts │ │ ├── extractUnavailableFields.ts │ │ ├── finalizeGatewayRequest.ts │ │ ├── getDocumentMetadata.ts │ │ ├── getTypeInfo.ts │ │ ├── index.ts │ │ ├── isPrototypePollutingKey.ts │ │ ├── leftOver.ts │ │ ├── mergeFields.ts │ │ ├── prepareGatewayDocument.ts │ │ ├── resolveExternalValue.ts │ │ ├── subschemaConfig.ts │ │ ├── symbols.ts │ │ ├── types.ts │ │ └── updateArguments.ts │ └── tests │ │ ├── batchExecution.test.ts │ │ ├── createRequest.test.ts │ │ ├── delegateToSchema.test.ts │ │ ├── errors.test.ts │ │ ├── extractUnavailableFields.test.ts │ │ ├── finalizeGatewayRequest.test.ts │ │ ├── prepareGatewayDocument.test.ts │ │ └── transforms.test.ts ├── executors │ ├── common │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ └── src │ │ │ └── index.ts │ ├── graphql-ws │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ ├── src │ │ │ └── index.ts │ │ └── tests │ │ │ └── graphql-ws.test.ts │ └── http │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ ├── src │ │ ├── createFormDataFromVariables.ts │ │ ├── handleEventStreamResponse.ts │ │ ├── handleMultipartMixedResponse.ts │ │ ├── index.ts │ │ ├── isGraphQLUpload.ts │ │ ├── isLiveQueryOperationDefinitionNode.ts │ │ ├── prepareGETUrl.ts │ │ └── utils.ts │ │ └── tests │ │ ├── apq.test.ts │ │ ├── buildHTTPExecutor.test.ts │ │ ├── handleEventStreamResponse.test.ts │ │ └── retry-timeout.test.ts ├── federation │ ├── CHANGELOG.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── managed-federation.ts │ │ ├── supergraph.ts │ │ └── utils.ts │ └── tests │ │ ├── .gitignore │ │ ├── __snapshots__ │ │ └── defer-stream.test.ts.snap │ │ ├── defer-stream.test.ts │ │ ├── error-handling.test.ts │ │ ├── federation-compatibility.test.ts │ │ ├── fixtures │ │ ├── .gitignore │ │ ├── gateway │ │ │ └── supergraph.ts │ │ ├── optimizations │ │ │ └── awareness-of-other-fields.ts │ │ └── supergraphs │ │ │ ├── a.graphql │ │ │ ├── b.graphql │ │ │ ├── c.graphql │ │ │ └── d.graphql │ │ ├── getKeyFnForFederation.test.ts │ │ ├── getStitchedSchemaFromLocalSchemas.ts │ │ ├── managed-federation.test.ts │ │ ├── optimizations.test.ts │ │ ├── queries.test.ts │ │ ├── shared-root.test.ts │ │ ├── subscription.test.ts │ │ ├── supergraphs.test.ts │ │ └── unavailable-subgraph.test.ts ├── fusion-runtime │ ├── CHANGELOG.md │ ├── package.json │ ├── scripts │ │ └── replace-import-with-require.mjs │ ├── src │ │ ├── executor.ts │ │ ├── federation │ │ │ ├── subgraph.ts │ │ │ └── supergraph.ts │ │ ├── index.ts │ │ ├── unifiedGraphManager.ts │ │ └── utils.ts │ └── tests │ │ ├── __snapshots__ │ │ └── runtime.test.ts.snap │ │ ├── polling.test.ts │ │ ├── runtime.test.ts │ │ └── utils.ts ├── gateway │ ├── CHANGELOG.md │ ├── bun.Dockerfile │ ├── bun_e2e.Dockerfile │ ├── node.Dockerfile │ ├── node_e2e.Dockerfile │ ├── package.json │ ├── rollup.config.binary.js │ ├── rollup.config.js │ ├── scripts │ │ ├── inject-version.ts │ │ ├── install-sea-packed-deps.cjs │ │ ├── package-binary.ts │ │ └── postject.d.ts │ ├── sea-config.json │ └── src │ │ ├── bin.ts │ │ ├── cli.ts │ │ ├── commands │ │ ├── handleFork.ts │ │ ├── handleLoggingOption.ts │ │ ├── handleReportingConfig.ts │ │ ├── index.ts │ │ ├── proxy.ts │ │ ├── subgraph.ts │ │ └── supergraph.ts │ │ ├── config.ts │ │ ├── getMaxConcurrency.ts │ │ ├── globals.d.ts │ │ ├── index.ts │ │ └── servers │ │ ├── bun.ts │ │ ├── nodeHttp.ts │ │ ├── startServerForRuntime.ts │ │ └── types.ts ├── importer │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── debug.ts │ │ ├── hooks.ts │ │ ├── index.ts │ │ └── transpile.ts │ └── tests │ │ ├── fixtures │ │ ├── basic.cts │ │ ├── basic.ts │ │ └── syntax-error.ts │ │ └── transpile.spec.ts ├── logger-json │ ├── CHANGELOG.md │ ├── package.json │ └── src │ │ └── index.ts ├── logger-pino │ ├── CHANGELOG.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tests │ │ └── pino.spec.ts ├── logger-winston │ ├── CHANGELOG.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tests │ │ └── winston.spec.ts ├── nestjs │ ├── CHANGELOG.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tests │ │ └── nestjs.test.ts ├── plugins │ ├── aws-sigv4 │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ ├── src │ │ │ ├── index.ts │ │ │ ├── plugin.ts │ │ │ └── types.ts │ │ └── tests │ │ │ ├── aws-sigv4-incoming.test.ts │ │ │ └── aws-sigv4-outgoing.test.ts │ ├── deduplicate-request │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ ├── src │ │ │ └── index.ts │ │ └── tests │ │ │ └── useDeduplicateRequest.test.ts │ ├── hmac-upstream-signature │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ ├── src │ │ │ └── index.ts │ │ └── tests │ │ │ └── hmac-upstream-signature.spec.ts │ ├── jwt-auth │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ ├── src │ │ │ └── index.ts │ │ └── tests │ │ │ ├── auth-directives.spec.ts │ │ │ └── useJWT.spec.ts │ ├── opentelemetry │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ ├── src │ │ │ ├── attributes.ts │ │ │ ├── index.ts │ │ │ ├── plugin.ts │ │ │ ├── processors.ts │ │ │ └── spans.ts │ │ └── tests │ │ │ └── useOpenTelemetry.spec.ts │ └── prometheus │ │ ├── CHANGELOG.md │ │ ├── grafana.json │ │ ├── package.json │ │ ├── src │ │ └── index.ts │ │ └── tests │ │ └── prometheus.spec.ts ├── pubsub │ ├── CHANGELOG.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── pubsub.ts │ └── tests │ │ └── pubsub.test.ts ├── runtime │ ├── CHANGELOG.md │ ├── package.json │ ├── scripts │ │ └── generate-landing-page-html.ts │ ├── src │ │ ├── createGatewayRuntime.ts │ │ ├── fetchers │ │ │ └── graphos.ts │ │ ├── getDefaultLogger.ts │ │ ├── getGraphQLWSOptions.ts │ │ ├── getProxyExecutor.ts │ │ ├── getReportingPlugin.ts │ │ ├── handleUnifiedGraphConfig.ts │ │ ├── index.ts │ │ ├── landing-page-html.ts │ │ ├── landing-page.html │ │ ├── plugins │ │ │ ├── demand-control │ │ │ │ └── calculateCost.ts │ │ │ ├── useCacheDebug.ts │ │ │ ├── useContentEncoding.ts │ │ │ ├── useCustomAgent.ts │ │ │ ├── useCustomFetch.ts │ │ │ ├── useDelegationPlanDebug.ts │ │ │ ├── useDemandControl.ts │ │ │ ├── useFetchDebug.ts │ │ │ ├── useHiveConsole.ts │ │ │ ├── usePropagateHeaders.ts │ │ │ ├── useRequestId.ts │ │ │ ├── useRetryOnSchemaReload.ts │ │ │ ├── useStaticFiles.ts │ │ │ ├── useSubgraphErrorPlugin.ts │ │ │ ├── useSubgraphExecuteDebug.ts │ │ │ ├── useUpstreamCancel.ts │ │ │ ├── useUpstreamRetry.ts │ │ │ ├── useUpstreamTimeout.ts │ │ │ └── useWebhooks.ts │ │ ├── productLogo.ts │ │ ├── types.ts │ │ └── utils.ts │ └── tests │ │ ├── __snapshots__ │ │ └── hive.spec.ts.snap │ │ ├── cache-control.test.ts │ │ ├── contentEncoding.test.ts │ │ ├── customAgent.spec.ts │ │ ├── demand-control.test.ts │ │ ├── gateway-runtime.spec.ts │ │ ├── graphos.test.ts │ │ ├── hive.spec.ts │ │ ├── instrumentation.spec.ts │ │ ├── propagateHeaders.spec.ts │ │ ├── schema-reload.test.ts │ │ ├── subgraph-down.test.ts │ │ ├── subgraph-errors.test.ts │ │ ├── subscriptions.test.ts │ │ ├── supergraph.graphql │ │ ├── sync.test.ts │ │ ├── upstream-retry.test.ts │ │ ├── upstream-timeout.test.ts │ │ └── upstreamCancellation.spec.ts ├── signal │ ├── CHANGELOG.md │ ├── package.json │ ├── src │ │ ├── abortSignalAny.ts │ │ └── index.ts │ └── tests │ │ └── abortSignalAny.test.ts ├── stitch │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── createDelegationPlanBuilder.ts │ │ ├── createMergedTypeResolver.ts │ │ ├── definitions.ts │ │ ├── executor.ts │ │ ├── getFieldsNotInSubschema.ts │ │ ├── index.ts │ │ ├── memoize5of7.ts │ │ ├── mergeCandidates.ts │ │ ├── mergeDirectives.ts │ │ ├── mergeValidations.ts │ │ ├── relay.ts │ │ ├── selectionSetArgs.ts │ │ ├── stitchSchemas.ts │ │ ├── stitchingInfo.ts │ │ ├── subschemaConfigTransforms │ │ │ ├── index.ts │ │ │ ├── isolateComputedFieldsTransformer.ts │ │ │ └── splitMergedTypeEntryPointsTransformer.ts │ │ ├── typeCandidates.ts │ │ ├── typeFromAST.ts │ │ └── types.ts │ └── tests │ │ ├── alternateStitchSchemas.test.ts │ │ ├── batchDelegationPath.test.ts │ │ ├── createDelegationPlanBuilder.test.ts │ │ ├── dataloader.test.ts │ │ ├── errors.test.ts │ │ ├── example.test.ts │ │ ├── extendedInterface.test.ts │ │ ├── fieldSelectionSets.test.ts │ │ ├── isolateComputedFieldsTransformer.test.ts │ │ ├── mergeAbstractTypes.test.ts │ │ ├── mergeComputedFields.test.ts │ │ ├── mergeConflicts.test.ts │ │ ├── mergeDefinitions.test.ts │ │ ├── mergeFailures.test.ts │ │ ├── mergeInterfaces.test.ts │ │ ├── mergeMultipleEntryPoints.test.ts │ │ ├── mergeResolvers.test.ts │ │ ├── mergeValidations.test.ts │ │ ├── nestedRootTypes.test.ts │ │ ├── node.test.ts │ │ ├── operationDirectives.test.ts │ │ ├── relay.spec.ts │ │ ├── selectionSetArgs.test.ts │ │ ├── selectionSets.test.ts │ │ ├── splitMergedTypeEntryPointsTransformer.test.ts │ │ ├── stitchSchemas.test.ts │ │ ├── stitchingexecutor.test.ts │ │ ├── transforms.test.ts │ │ ├── typeMerging.test.ts │ │ ├── typeMergingWithDirectives.test.ts │ │ ├── typeMergingWithExtensions.test.ts │ │ ├── typeMergingWithInterfaces.test.ts │ │ └── unknownType.test.ts ├── stitching-directives │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── defaultStitchingDirectiveOptions.ts │ │ ├── extractVariables.ts │ │ ├── federationToStitchingSDL.ts │ │ ├── getSourcePaths.ts │ │ ├── index.ts │ │ ├── parseMergeArgsExpr.ts │ │ ├── pathsFromSelectionSet.ts │ │ ├── preparseMergeArgsExpr.ts │ │ ├── properties.ts │ │ ├── stitchingDirectives.ts │ │ ├── stitchingDirectivesTransformer.ts │ │ ├── stitchingDirectivesValidator.ts │ │ └── types.ts │ └── tests │ │ ├── extractVariables.test.ts │ │ ├── federationToStitchingSDL.test.ts │ │ ├── mergeComputedFields.test.ts │ │ ├── parseMergeArgsExpr.test.ts │ │ ├── pathsFromSelectionSets.test.ts │ │ ├── preparseMergeArgsExpr.test.ts │ │ ├── properties.test.ts │ │ ├── reproductions.test.ts │ │ ├── stitchingDirectivesTransformer.test.ts │ │ └── stitchingDirectivesValidator.test.ts ├── transports │ ├── common │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ └── src │ │ │ ├── ObjMap.ts │ │ │ ├── index.ts │ │ │ └── types.ts │ ├── http-callback │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ └── src │ │ │ └── index.ts │ ├── http │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ ├── src │ │ │ └── index.ts │ │ └── tests │ │ │ └── http.spec.ts │ └── ws │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ ├── src │ │ └── index.ts │ │ └── tests │ │ └── ws.spec.ts └── wrap │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ ├── generateProxyingResolvers.ts │ ├── index.ts │ ├── introspect.ts │ ├── transforms │ │ ├── ExtractField.ts │ │ ├── FilterInputObjectFields.ts │ │ ├── FilterInterfaceFields.ts │ │ ├── FilterObjectFieldDirectives.ts │ │ ├── FilterObjectFields.ts │ │ ├── FilterRootFields.ts │ │ ├── FilterTypes.ts │ │ ├── HoistField.ts │ │ ├── MapFields.ts │ │ ├── MapLeafValues.ts │ │ ├── MoveRootField.ts │ │ ├── PruneSchema.ts │ │ ├── RemoveObjectFieldDeprecations.ts │ │ ├── RemoveObjectFieldDirectives.ts │ │ ├── RemoveObjectFieldsWithDeprecation.ts │ │ ├── RemoveObjectFieldsWithDirective.ts │ │ ├── RenameInputObjectFields.ts │ │ ├── RenameInterfaceFields.ts │ │ ├── RenameObjectFieldArguments.ts │ │ ├── RenameObjectFields.ts │ │ ├── RenameRootFields.ts │ │ ├── RenameRootTypes.ts │ │ ├── RenameTypes.ts │ │ ├── TransformCompositeFields.ts │ │ ├── TransformEnumValues.ts │ │ ├── TransformInputObjectFields.ts │ │ ├── TransformInterfaceFields.ts │ │ ├── TransformObjectFields.ts │ │ ├── TransformQuery.ts │ │ ├── TransformRootFields.ts │ │ ├── WrapFields.ts │ │ ├── WrapQuery.ts │ │ ├── WrapType.ts │ │ └── index.ts │ ├── types.ts │ └── wrapSchema.ts │ └── tests │ ├── fragmentsAreNotDuplicated.test.ts │ ├── gatsbyTransforms.test.ts │ ├── makeRemoteExecutableSchema.test.ts │ ├── moveRootField.test.ts │ ├── requests.test.ts │ ├── transformFilterInputObjectFields.test.ts │ ├── transformFilterInterfaceFields.test.ts │ ├── transformFilterObjectFieldDirectives.test.ts │ ├── transformFilterObjectFields.test.ts │ ├── transformFilterRootFields.test.ts │ ├── transformFilterTypes.test.ts │ ├── transformMapLeafValues.test.ts │ ├── transformRemoveObjectFieldDeprecations.test.ts │ ├── transformRemoveObjectFieldDirectives.test.ts │ ├── transformRemoveObjectFieldsWithDeprecation.test.ts │ ├── transformRemoveObjectFieldsWithDirective.test.ts │ ├── transformRenameInputObjectFields.test.ts │ ├── transformRenameInterfaceFields.test.ts │ ├── transformRenameObjectFieldArguments.test.ts │ ├── transformRenameObjectFields.test.ts │ ├── transformRenameRootFields.test.ts │ ├── transformRenameRootTypes.test.ts │ ├── transformRenameTypes.test.ts │ ├── transformTransformCompositeFields.test.ts │ ├── transformTransformEnumValues.test.ts │ ├── transformTransformQuery.test.ts │ ├── transformWrapFields.test.ts │ ├── transformWrapQuery.test.ts │ └── transforms.test.ts ├── renovate.json ├── scripts └── install-winsdk.ps1 ├── tsconfig.json ├── vitest-jest.js ├── vitest.config.ts ├── vitest.projects.ts └── yarn.lock /.changeset/@graphql-hive_gateway-runtime-1195-dependencies.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@graphql-hive/gateway-runtime': patch 3 | --- 4 | 5 | dependencies updates: 6 | 7 | - Updated dependency [`@types/node@^22.15.29` ↗︎](https://www.npmjs.com/package/@types/node/v/22.15.29) (from `^22.15.27`, in `dependencies`) 8 | -------------------------------------------------------------------------------- /.changeset/@graphql-hive_plugin-aws-sigv4-1195-dependencies.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@graphql-hive/plugin-aws-sigv4': patch 3 | --- 4 | 5 | dependencies updates: 6 | 7 | - Updated dependency [`@aws-sdk/client-sts@^3.821.0` ↗︎](https://www.npmjs.com/package/@aws-sdk/client-sts/v/3.821.0) (from `^3.817.0`, in `dependencies`) 8 | -------------------------------------------------------------------------------- /.changeset/@graphql-hive_plugin-aws-sigv4-1203-dependencies.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@graphql-hive/plugin-aws-sigv4': patch 3 | --- 4 | 5 | dependencies updates: 6 | 7 | - Updated dependency [`@aws-sdk/client-sts@^3.823.0` ↗︎](https://www.npmjs.com/package/@aws-sdk/client-sts/v/3.823.0) (from `^3.821.0`, in `dependencies`) 8 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.3/schema.json", 3 | "changelog": [ 4 | "@changesets/changelog-github", 5 | { "repo": "graphql-hive/gateway" } 6 | ], 7 | "commit": false, 8 | "fixed": [], 9 | "linked": [], 10 | "access": "public", 11 | "baseBranch": "main", 12 | "updateInternalDependencies": "patch", 13 | "ignore": [], 14 | "privatePackages": { 15 | "tag": false, 16 | "version": false 17 | }, 18 | "snapshot": { 19 | "useCalculatedVersion": true, 20 | "prereleaseTemplate": "{tag}-{commit}" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.github/workflows/bench.yml: -------------------------------------------------------------------------------- 1 | name: Bench 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | env: 13 | NODE_NO_WARNINGS: 1 14 | 15 | jobs: 16 | bench: 17 | strategy: 18 | matrix: 19 | e2e_runner: [node, bun] 20 | name: ${{matrix.e2e_runner}} 21 | runs-on: ubuntu-latest 22 | steps: 23 | - name: Checkout 24 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 25 | - name: Set up env 26 | uses: the-guild-org/shared-config/setup@v1 27 | with: 28 | node-version-file: .node-version 29 | - name: Bench 30 | run: ${{matrix.e2e_runner == 'bun' && './node_modules/.bin/bun' || 'yarn'}} bench 31 | env: 32 | E2E_GATEWAY_RUNNER: ${{matrix.e2e_runner}} 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | bundle/ 5 | .yarn/* 6 | !.yarn/patches 7 | !.yarn/releases 8 | !.yarn/custom-plugins 9 | tsconfig.tsbuildinfo 10 | sea-prep.blob 11 | hive-gateway 12 | .cache/ 13 | *.pem 14 | /examples/**/*/supergraph.graphql 15 | .helix/config.toml 16 | .helix/languages.toml 17 | /e2e/**/*/memtest-memory-usage_*.svg 18 | /e2e/**/*/*.heapsnapshot 19 | /e2e/**/*/*.heapprofile 20 | /e2e/**/*/loadtest.out 21 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | v24 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | provenance=true 2 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | .node-version -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .yarn/* 2 | !.yarn/custom-plugins 3 | Dockerfile 4 | packages/runtime/src/landing-page-html.ts 5 | __generated__ 6 | .changeset/* 7 | !.changeset/README.md 8 | !.changeset/config.json 9 | .wrangler/ 10 | *.Dockerfile 11 | /examples/ 12 | /packages/importer/tests/fixtures/syntax-error.ts 13 | /e2e/config-syntax-error/gateway.config.ts 14 | /e2e/config-syntax-error/custom-resolvers.ts 15 | CHANGELOG.md 16 | -------------------------------------------------------------------------------- /.prettierrc.yml: -------------------------------------------------------------------------------- 1 | singleQuote: true 2 | plugins: 3 | - '@ianvs/prettier-plugin-sort-imports' 4 | - prettier-plugin-pkg 5 | - prettier-plugin-sh 6 | importOrderParserPlugins: 7 | - typescript 8 | - jsx 9 | - decorators-legacy 10 | - explicitResourceManagement 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib" 3 | } 4 | -------------------------------------------------------------------------------- /.yarn/patches/ioredis-mock-npm-8.9.0-530d4422b9.patch: -------------------------------------------------------------------------------- 1 | diff --git a/lib/index.js b/lib/index.js 2 | index a82c2975d19bfcce4179d27594e26e0c47ef7a1f..c137fc868769255aff7d3d83e884431e6c34057b 100644 3 | --- a/lib/index.js 4 | +++ b/lib/index.js 5 | @@ -6274,9 +6274,14 @@ var defaultOptions = { 6 | RedisMock.Command = Command; 7 | RedisMock.Cluster = class extends RedisMock { 8 | constructor(nodesOptions, clusterOptions) { 9 | - clusterOptions && clusterOptions.redisOptions ? super(clusterOptions.redisOptions) : super(), nodesOptions.forEach( 10 | + if (clusterOptions && clusterOptions.redisOptions) { 11 | + super(clusterOptions.redisOptions); 12 | + } else { 13 | + super(); 14 | + } 15 | + nodesOptions.forEach( 16 | (options) => this.clusterNodes.all.push(new RedisMock(options)) 17 | - ); 18 | + ); 19 | } 20 | clusterNodes = { 21 | all: [], 22 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | yarnPath: .yarn/releases/yarn-4.9.1.cjs # TODO: corepack does not work in github actions on windows 2 | nodeLinker: node-modules 3 | npmPublishRegistry: https://registry.npmjs.org 4 | npmAuthToken: ${NPM_TOKEN:-} 5 | checksumBehavior: ignore 6 | plugins: 7 | - ./.yarn/custom-plugins/snapshot-no-semver-range.cjs 8 | -------------------------------------------------------------------------------- /DEPS_RESOLUTIONS_NOTES.md: -------------------------------------------------------------------------------- 1 | # Notes about dependency resolutions in [package.json](/package.json) 2 | 3 | Here we collect reasons and write explanations about why some resolutions or patches have been added. 4 | 5 | ### pkgroll 6 | 7 | 1. https://github.com/privatenumber/pkgroll/issues/101 (added `interop: "auto"` to `getRollupConfigs` outputs) 8 | 1. Skip libchecking while generating type declarations because we never bundle `@types` by disabling `respectExternal` ([read more](https://github.com/Swatinem/rollup-plugin-dts?tab=readme-ov-file#what-to-expect)) 9 | 10 | ### tsx 11 | 12 | 1. https://github.com/privatenumber/tsx/issues/159#issuecomment-2473632866 (did what was suggested) 13 | 14 | ### vitest-tsconfig-paths 15 | 16 | 1. Resolve tsconfig paths in modules that have been [inlined](https://vitest.dev/config/#server-deps-inline). 17 | 18 | ### @memlab/core 19 | 20 | 1. Define package.json#export for `@memlab/core/Types` 21 | 1. Define package.json#export for `@memlab/core/Utils` 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Hive GraphQL Platform](https://the-guild.dev/graphql/hive/github-org-image.png) 2 | 3 | # Hive Gateway 4 | 5 | A fully open-source MIT-licensed GraphQL API gateway that can act as a [GraphQL federation](https://the-guild.dev/graphql/hive/federation) Gateway or a Proxy Gateway for any GraphQL services. 6 | 7 | It can be run as a standalone binary, a Docker Image, or as a JavaScript package (e.g. within Node.js, Bun, Deno, Google Cloud Functions, Azure Functions or Cloudflare Workers) 8 | -------------------------------------------------------------------------------- /babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { targets: { node: process.versions.node.split('.')[0] } }, 6 | ], 7 | '@babel/preset-typescript', 8 | ], 9 | plugins: [ 10 | ['@babel/plugin-transform-class-static-block', { version: '2023-11' }], 11 | ['@babel/plugin-proposal-decorators', { version: '2023-11' }], 12 | '@babel/plugin-transform-class-properties', 13 | '@babel/plugin-proposal-explicit-resource-management', 14 | ], 15 | }; 16 | -------------------------------------------------------------------------------- /e2e/apq-subgraphs/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | 3 | let fetchCnt = 0; 4 | export const gatewayConfig = defineConfig({ 5 | transportEntries: { 6 | greetings: { 7 | options: { 8 | apq: true, 9 | }, 10 | }, 11 | }, 12 | plugins: () => [ 13 | { 14 | onFetch({ options }) { 15 | fetchCnt++; 16 | process.stdout.write(`fetch ${fetchCnt} ${options.body}\n`); 17 | }, 18 | }, 19 | ], 20 | }); 21 | -------------------------------------------------------------------------------- /e2e/apq-subgraphs/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | import { Opts } from '@internal/testing'; 6 | 7 | const opts = Opts(process.argv); 8 | 9 | export const composeConfig = defineConfig({ 10 | subgraphs: [ 11 | { 12 | sourceHandler: loadGraphQLHTTPSubgraph('greetings', { 13 | endpoint: `http://localhost:${opts.getServicePort('greetings')}/graphql`, 14 | }), 15 | }, 16 | ], 17 | }); 18 | -------------------------------------------------------------------------------- /e2e/apq-subgraphs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/apq-subgraphs", 3 | "private": true, 4 | "devDependencies": { 5 | "@apollo/server": "^4.12.2", 6 | "@graphql-mesh/compose-cli": "^1.4.1", 7 | "graphql": "^16.9.0", 8 | "tslib": "^2.8.1" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /e2e/apq-subgraphs/services/greetings.ts: -------------------------------------------------------------------------------- 1 | import { ApolloServer } from '@apollo/server'; 2 | import { startStandaloneServer } from '@apollo/server/standalone'; 3 | import { Opts } from '@internal/testing'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | const apolloServer = new ApolloServer({ 8 | typeDefs: /* GraphQL */ ` 9 | type Query { 10 | hello: String 11 | } 12 | `, 13 | resolvers: { 14 | Query: { 15 | hello: () => 'world', 16 | }, 17 | }, 18 | }); 19 | 20 | startStandaloneServer(apolloServer, { 21 | listen: { port: opts.getServicePort('greetings') }, 22 | }).catch((e) => { 23 | console.error(e); 24 | process.exit(1); 25 | }); 26 | -------------------------------------------------------------------------------- /e2e/armor-options/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/armor-options", 3 | "private": true 4 | } 5 | -------------------------------------------------------------------------------- /e2e/auto-type-merging/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/auto-type-merging", 3 | "private": true, 4 | "devDependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "graphql": "^16.9.0", 8 | "graphql-yoga": "^5.13.5", 9 | "tslib": "^2.8.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/auto-type-merging/services/vaccination.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { Opts } from '@internal/testing'; 3 | import { createSchema, createYoga } from 'graphql-yoga'; 4 | 5 | export const yoga = createYoga({ 6 | schema: createSchema({ 7 | typeDefs: /* GraphQL */ ` 8 | scalar BigInt 9 | 10 | type Query { 11 | pet_by_id(id: BigInt!): Pet 12 | } 13 | 14 | type Pet { 15 | id: BigInt! 16 | vaccinated: Boolean! 17 | } 18 | `, 19 | resolvers: { 20 | Query: { 21 | pet_by_id: async (_root, args, _context, _info) => { 22 | return { 23 | id: args.id, 24 | vaccinated: false, 25 | }; 26 | }, 27 | }, 28 | }, 29 | }), 30 | }); 31 | 32 | const port = Opts(process.argv).getServicePort('vaccination', true); 33 | 34 | createServer(yoga).listen(port, () => { 35 | console.log(`Vaccination service listening on http://localhost:${port}`); 36 | }); 37 | -------------------------------------------------------------------------------- /e2e/aws-sigv4/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | 3 | export const gatewayConfig = defineConfig({ 4 | awsSigv4: { 5 | outgoing: { 6 | region: 'us-east-1', 7 | serviceName: 'lambda', 8 | }, 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /e2e/aws-sigv4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/aws-sigv4", 3 | "private": true, 4 | "devDependencies": { 5 | "@apollo/subgraph": "^2.11.0", 6 | "aws4-express": "^0.11.0", 7 | "express": "^5.0.0", 8 | "graphql": "^16.9.0", 9 | "graphql-yoga": "^5.13.5", 10 | "tslib": "^2.8.1" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /e2e/cloudflare-workers/.gitignore: -------------------------------------------------------------------------------- 1 | .wrangler 2 | -------------------------------------------------------------------------------- /e2e/cloudflare-workers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/cloudflare-workers", 3 | "private": true, 4 | "scripts": { 5 | "start": "wrangler dev src/index.ts" 6 | }, 7 | "devDependencies": { 8 | "@cloudflare/workers-types": "^4.20250605.0", 9 | "@graphql-hive/gateway-runtime": "workspace:*", 10 | "graphql": "^16.9.0", 11 | "wrangler": "^4.19.1" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /e2e/cloudflare-workers/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "module": "esnext", 6 | "lib": ["esnext"], 7 | "moduleResolution": "bundler", 8 | "types": ["@cloudflare/workers-types/experimental"] 9 | }, 10 | "include": ["./**/*.ts", "../src/env.d.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /e2e/cloudflare-workers/wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "hive-gateway" 2 | main = "src/index.ts" 3 | compatibility_date = "2024-01-01" 4 | 5 | [alias] 6 | "@graphql-tools/wrap" = "../../packages/wrap/src/index.ts" 7 | "@graphql-tools/batch-delegate" = "../../packages/batch-delegate/src/index.ts" 8 | "@graphql-tools/delegate" = "../../packages/delegate/src/index.ts" -------------------------------------------------------------------------------- /e2e/config-syntax-error/custom-resolvers.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck -- syntax error intentionally 2 | 3 | import { GatewayContext } from '@graphql-hive/gateway'; 4 | import { IResolvers } from '@graphql-tools/utils'; 5 | 6 | export const customResolvers: IResolvers = { 7 | Query: { 8 | bye() hello { 9 | return 'world'; 10 | }, 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /e2e/config-syntax-error/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | import { customResolvers } from './custom-resolvers'; 3 | 4 | export const gatewayConfig = defineConfig({ 5 | additionalResolvers: [customResolvers], 6 | }); 7 | -------------------------------------------------------------------------------- /e2e/config-syntax-error/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | import { Opts } from '@internal/testing'; 6 | 7 | const opts = Opts(process.argv); 8 | 9 | export const composeConfig = defineConfig({ 10 | subgraphs: [ 11 | { 12 | sourceHandler: loadGraphQLHTTPSubgraph('hello', { 13 | endpoint: `http://localhost:${opts.getServicePort('hello')}/graphql`, 14 | }), 15 | }, 16 | ], 17 | additionalTypeDefs: /* GraphQL */ ` 18 | extend type Query { 19 | bye: String! 20 | } 21 | `, 22 | }); 23 | -------------------------------------------------------------------------------- /e2e/config-syntax-error/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/config-syntax-error", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@graphql-tools/utils": "^10.7.2", 7 | "graphql": "^16.9.0", 8 | "tslib": "^2.8.1" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /e2e/config-syntax-error/services/hello.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { Opts } from '@internal/testing'; 3 | import { createSchema, createYoga } from 'graphql-yoga'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | createServer( 8 | createYoga({ 9 | maskedErrors: false, 10 | schema: createSchema({ 11 | typeDefs: /* GraphQL */ ` 12 | type Query { 13 | hello: String! 14 | } 15 | `, 16 | resolvers: { 17 | Query: { 18 | hello: () => 'world', 19 | }, 20 | }, 21 | }), 22 | }), 23 | ).listen(opts.getServicePort('hello')); 24 | -------------------------------------------------------------------------------- /e2e/demand-control/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | 3 | export const gatewayConfig = defineConfig({ 4 | demandControl: { 5 | includeExtensionMetadata: true, 6 | maxCost: 35, 7 | }, 8 | }); 9 | -------------------------------------------------------------------------------- /e2e/demand-control/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/demand-control", 3 | "private": true, 4 | "dependencies": { 5 | "@apollo/subgraph": "^2.11.0", 6 | "graphql": "^16.9.0", 7 | "graphql-yoga": "^5.13.5", 8 | "tslib": "^2.8.1" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /e2e/extra-fields/extra-fields.e2e.ts: -------------------------------------------------------------------------------- 1 | import { createTenv } from '@internal/e2e'; 2 | import { expect, it } from 'vitest'; 3 | 4 | const { gateway, service } = createTenv(__dirname); 5 | 6 | it('resolves extra fields', async () => { 7 | const { execute } = await gateway({ 8 | supergraph: { 9 | with: 'mesh', 10 | services: [await service('foo'), await service('bar')], 11 | }, 12 | }); 13 | await expect( 14 | execute({ 15 | query: /* GraphQL */ ` 16 | query FooBarFoo { 17 | foo { 18 | id 19 | bar { 20 | id 21 | foo { 22 | id 23 | } 24 | } 25 | } 26 | } 27 | `, 28 | }), 29 | ).resolves.toMatchInlineSnapshot(` 30 | { 31 | "data": { 32 | "foo": { 33 | "bar": { 34 | "foo": { 35 | "id": "1", 36 | }, 37 | "id": "1", 38 | }, 39 | "id": "1", 40 | }, 41 | }, 42 | } 43 | `); 44 | }); 45 | -------------------------------------------------------------------------------- /e2e/extra-fields/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/extra-fields", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "graphql": "^16.9.0", 7 | "graphql-yoga": "^5.13.5", 8 | "tslib": "^2.8.1" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /e2e/extra-fields/services/bar.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { Opts } from '@internal/testing'; 3 | import { createSchema, createYoga } from 'graphql-yoga'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | createServer( 8 | createYoga({ 9 | schema: createSchema({ 10 | typeDefs: /* GraphQL */ ` 11 | type Query { 12 | bar: Bar 13 | } 14 | 15 | type Bar { 16 | id: ID! 17 | } 18 | `, 19 | resolvers: { 20 | Query: { 21 | bar() { 22 | return { id: '1' }; 23 | }, 24 | }, 25 | }, 26 | }), 27 | }), 28 | ).listen(opts.getServicePort('bar')); 29 | -------------------------------------------------------------------------------- /e2e/extra-fields/services/foo.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { Opts } from '@internal/testing'; 3 | import { createSchema, createYoga } from 'graphql-yoga'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | createServer( 8 | createYoga({ 9 | schema: createSchema({ 10 | typeDefs: /* GraphQL */ ` 11 | type Query { 12 | foo: Foo 13 | } 14 | 15 | type Foo { 16 | id: ID! 17 | } 18 | `, 19 | resolvers: { 20 | Query: { 21 | foo() { 22 | return { id: '1' }; 23 | }, 24 | }, 25 | }, 26 | }), 27 | }), 28 | ).listen(opts.getServicePort('foo')); 29 | -------------------------------------------------------------------------------- /e2e/federation-batching-plan/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/federation-batching-plan", 3 | "private": true, 4 | "dependencies": { 5 | "@apollo/server": "^4.12.2", 6 | "@apollo/subgraph": "^2.11.0", 7 | "graphql": "^16.9.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /e2e/federation-example/federation-example.e2e.ts: -------------------------------------------------------------------------------- 1 | import { createExampleSetup, createTenv } from '@internal/e2e'; 2 | import { expect, it } from 'vitest'; 3 | 4 | const { gateway } = createTenv(__dirname); 5 | const { supergraph, query, result } = createExampleSetup(__dirname); 6 | it('should execute', async () => { 7 | const { execute } = await gateway({ 8 | supergraph: await supergraph(), 9 | }); 10 | await expect( 11 | execute({ 12 | query, 13 | }), 14 | ).resolves.toEqual(result); 15 | }); 16 | -------------------------------------------------------------------------------- /e2e/federation-example/federation-example.memtest.ts: -------------------------------------------------------------------------------- 1 | import { createExampleSetup, createTenv } from '@internal/e2e'; 2 | import { memtest } from '@internal/perf/memtest'; 3 | 4 | const cwd = __dirname; 5 | 6 | const { gateway } = createTenv(cwd); 7 | const { supergraph, query } = createExampleSetup(cwd); 8 | 9 | memtest( 10 | { 11 | cwd, 12 | query, 13 | }, 14 | async () => 15 | gateway({ 16 | supergraph: await supergraph(), 17 | }), 18 | ); 19 | -------------------------------------------------------------------------------- /e2e/federation-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/federation-example", 3 | "private": true, 4 | "devDependencies": { 5 | "@apollo/server": "^4.12.2", 6 | "@apollo/subgraph": "^2.11.0", 7 | "graphql": "^16.9.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /e2e/federation-example/services/apollo-gateway.ts: -------------------------------------------------------------------------------- 1 | import { readFileSync } from 'fs'; 2 | import { ApolloGateway } from '@apollo/gateway'; 3 | import { ApolloServer } from '@apollo/server'; 4 | import { startStandaloneServer } from '@apollo/server/standalone'; 5 | import { Opts } from '@internal/testing'; 6 | 7 | const opts = Opts(process.argv); 8 | const port = opts.getServicePort('apollo-gateway'); 9 | 10 | async function main() { 11 | const supergraph = process.env['SUPERGRAPH']; 12 | if (!supergraph) { 13 | throw new Error('SUPERGRAPH env var is required'); 14 | } 15 | const supergraphSdl = readFileSync(supergraph, 'utf-8'); 16 | const server = new ApolloServer({ 17 | gateway: new ApolloGateway({ 18 | supergraphSdl, 19 | }), 20 | }); 21 | const { url } = await startStandaloneServer(server, { 22 | listen: { port }, 23 | }); 24 | console.log(`🚀 Gateway ready at ${url}`); 25 | } 26 | 27 | main().catch((error) => { 28 | console.error(error); 29 | process.exit(1); 30 | }); 31 | -------------------------------------------------------------------------------- /e2e/federation-mixed/federation-mixed.e2e.ts: -------------------------------------------------------------------------------- 1 | import { createExampleSetup, createTenv } from '@internal/e2e'; 2 | import { expect, it } from 'vitest'; 3 | 4 | const { service, gateway } = createTenv(__dirname); 5 | const exampleSetup = createExampleSetup(__dirname); 6 | 7 | it('should execute', async () => { 8 | const { execute } = await gateway({ 9 | supergraph: { 10 | with: 'mesh', 11 | services: [ 12 | await service('accounts'), 13 | await exampleSetup.service('inventory'), 14 | await exampleSetup.service('products'), 15 | await exampleSetup.service('reviews'), 16 | ], 17 | }, 18 | }); 19 | await expect( 20 | execute({ 21 | query: exampleSetup.query, 22 | }), 23 | ).resolves.toEqual(exampleSetup.result); 24 | }); 25 | -------------------------------------------------------------------------------- /e2e/federation-mixed/federation-mixed.memtest.ts: -------------------------------------------------------------------------------- 1 | import { createExampleSetup, createTenv } from '@internal/e2e'; 2 | import { memtest } from '@internal/perf/memtest'; 3 | 4 | const cwd = __dirname; 5 | 6 | const { service, gateway } = createTenv(cwd); 7 | const exampleSetup = createExampleSetup(cwd); 8 | 9 | memtest( 10 | { 11 | cwd, 12 | query: exampleSetup.query, 13 | }, 14 | async () => 15 | gateway({ 16 | supergraph: { 17 | with: 'mesh', 18 | services: [ 19 | await service('accounts'), 20 | await exampleSetup.service('inventory'), 21 | await exampleSetup.service('products'), 22 | await exampleSetup.service('reviews'), 23 | ], 24 | }, 25 | }), 26 | ); 27 | -------------------------------------------------------------------------------- /e2e/federation-mixed/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/federation-mixed", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "graphql": "^16.9.0", 8 | "tslib": "^2.8.1" 9 | }, 10 | "devDependencies": { 11 | "@apollo/server": "^4.12.2", 12 | "@apollo/subgraph": "^2.11.0", 13 | "fets": "^0.8.4" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /e2e/federation-mixed/services/accounts/index.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { Opts } from '@internal/testing'; 3 | import { server } from './server'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | const httpServer = createServer(server).listen(opts.getServicePort('accounts')); 8 | 9 | httpServer.once('error', (err) => { 10 | console.error(err); 11 | process.exit(1); 12 | }); 13 | -------------------------------------------------------------------------------- /e2e/federation-rate-limiting/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | 3 | const rateLimitTtl = parseInt(process.env['RATE_LIMIT_TTL'] || ''); 4 | if (isNaN(rateLimitTtl)) { 5 | throw new Error('RATE_LIMIT_TTL must be a number'); 6 | } 7 | 8 | export const gatewayConfig = defineConfig({ 9 | rateLimiting: [ 10 | { 11 | type: 'Query', 12 | field: 'users', 13 | max: 5, 14 | ttl: rateLimitTtl, 15 | identifier: 'anonymous', 16 | }, 17 | ], 18 | }); 19 | -------------------------------------------------------------------------------- /e2e/federation-rate-limiting/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/federation-rate-limiting", 3 | "private": true 4 | } 5 | -------------------------------------------------------------------------------- /e2e/federation-subscriptions-passthrough/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | type HTTPCallbackTransportOptions, 4 | type WSTransportOptions, 5 | } from '@graphql-hive/gateway'; 6 | 7 | export const gatewayConfig = defineConfig({ 8 | webhooks: true, 9 | transportEntries: { 10 | products: { 11 | options: { 12 | subscriptions: { 13 | kind: 'ws', 14 | location: '/subscriptions', 15 | options: { 16 | connectionParams: { 17 | token: '{context.headers.authorization}', 18 | }, 19 | } satisfies WSTransportOptions, 20 | }, 21 | }, 22 | }, 23 | reviews: { 24 | options: { 25 | subscriptions: { 26 | kind: 'http-callback', 27 | options: { 28 | public_url: process.env['PUBLIC_URL'], 29 | } satisfies HTTPCallbackTransportOptions, 30 | }, 31 | }, 32 | }, 33 | }, 34 | }); 35 | -------------------------------------------------------------------------------- /e2e/federation-subscriptions-passthrough/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/federation-subscriptions-passthrough", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/transport-ws": "workspace:^", 6 | "@whatwg-node/fetch": "^0.10.8", 7 | "graphql": "^16.9.0", 8 | "tslib": "^2.8.1" 9 | }, 10 | "devDependencies": { 11 | "@apollo/server": "^4.12.2", 12 | "@apollo/subgraph": "^2.11.0", 13 | "@repeaterjs/repeater": "^3.0.6", 14 | "@types/express": "^5.0.0", 15 | "@types/ws": "^8", 16 | "express": "^5.0.0", 17 | "graphql-sse": "^2.5.3", 18 | "graphql-ws": "^6.0.2", 19 | "ws": "^8.17.1" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /e2e/federation-subscriptions-passthrough/services/products/index.ts: -------------------------------------------------------------------------------- 1 | import { Opts } from '@internal/testing'; 2 | import { start } from './server'; 3 | 4 | const opts = Opts(process.argv); 5 | 6 | start(opts.getServicePort('products', true)).catch((err) => { 7 | console.error(err); 8 | process.exit(1); 9 | }); 10 | -------------------------------------------------------------------------------- /e2e/federation-subscriptions-passthrough/services/products/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | topProducts(first: Int = 3): [Product] 3 | } 4 | 5 | type Subscription { 6 | productPriceChanged: Product! 7 | newProduct: Product! 8 | } 9 | 10 | type Product @key(fields: "id") { 11 | id: ID! 12 | name: String! 13 | price: Int! 14 | } 15 | -------------------------------------------------------------------------------- /e2e/federation-subscriptions-passthrough/services/reviews/index.ts: -------------------------------------------------------------------------------- 1 | import { Opts } from '@internal/testing'; 2 | import { start } from './server'; 3 | 4 | const opts = Opts(process.argv); 5 | 6 | start(opts.getServicePort('reviews', true)).catch((err) => { 7 | console.error(err); 8 | process.exit(1); 9 | }); 10 | -------------------------------------------------------------------------------- /e2e/federation-subscriptions-passthrough/services/reviews/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend type Product @key(fields: "id") { 2 | id: ID! @external 3 | reviews: [Review!]! 4 | } 5 | 6 | type Review { 7 | score: Int! 8 | } 9 | 10 | type Subscription { 11 | countdown(from: Int!): Int 12 | newReview: Review! 13 | } 14 | -------------------------------------------------------------------------------- /e2e/file-upload/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | import { Opts } from '@internal/testing'; 6 | 7 | const opts = Opts(process.argv); 8 | 9 | export const composeConfig = defineConfig({ 10 | subgraphs: [ 11 | { 12 | sourceHandler: loadGraphQLHTTPSubgraph('bucket', { 13 | endpoint: `http://localhost:${opts.getServicePort('bucket')}/graphql`, 14 | }), 15 | }, 16 | ], 17 | }); 18 | -------------------------------------------------------------------------------- /e2e/file-upload/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/file-upload", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "graphql": "^16.9.0", 7 | "tslib": "^2.8.1" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /e2e/file-upload/services/bucket.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { Opts } from '@internal/testing'; 3 | import { createSchema, createYoga } from 'graphql-yoga'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | createServer( 8 | createYoga({ 9 | maskedErrors: false, 10 | schema: createSchema({ 11 | typeDefs: /* GraphQL */ ` 12 | scalar Upload # intentionally not "File" to test scalar name independence 13 | type Query { 14 | hello: String! 15 | } 16 | type Mutation { 17 | readFile(file: Upload!): String 18 | } 19 | `, 20 | resolvers: { 21 | Query: { 22 | hello: () => 'world', 23 | }, 24 | Mutation: { 25 | readFile(_parent, { file }: { file: File }) { 26 | return file.text(); 27 | }, 28 | }, 29 | }, 30 | }), 31 | }), 32 | ).listen(opts.getServicePort('bucket')); 33 | -------------------------------------------------------------------------------- /e2e/graceful-shutdown/graceful-shutdown.e2e.ts: -------------------------------------------------------------------------------- 1 | import { setTimeout } from 'timers/promises'; 2 | import { createExampleSetup, createTenv } from '@internal/e2e'; 3 | import { expect, it } from 'vitest'; 4 | 5 | const { gateway, gatewayRunner } = createTenv(__dirname); 6 | const { supergraph, query, result } = createExampleSetup(__dirname); 7 | 8 | it 9 | .skipIf(gatewayRunner.includes('docker')) 10 | .each(['SIGINT', 'SIGTERM'] as const)( 11 | 'should gracefully shut down on %s signal', 12 | async (signal) => { 13 | const gw = await gateway({ 14 | supergraph: await supergraph(), 15 | }); 16 | 17 | await expect( 18 | gw.execute({ 19 | query, 20 | }), 21 | ).resolves.toEqual(result); 22 | 23 | gw.kill(signal); 24 | 25 | await Promise.race([ 26 | gw.waitForExit, 27 | setTimeout(3_000).then(() => { 28 | expect.fail('Gateway did not exit on signal'); 29 | }), 30 | ]); 31 | }, 32 | ); 33 | -------------------------------------------------------------------------------- /e2e/graceful-shutdown/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/graceful-shutdown", 3 | "private": true 4 | } 5 | -------------------------------------------------------------------------------- /e2e/graphos-polling/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/graphos-polling", 3 | "type": "module", 4 | "private": true, 5 | "dependencies": { 6 | "@apollo/subgraph": "^2.11.0", 7 | "fastify": "^5.2.2", 8 | "graphql": "^16.10.0", 9 | "graphql-yoga": "^5.13.5", 10 | "pino-pretty": "^13.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /e2e/graphos-polling/services/upstream_good.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'node:http'; 2 | import { buildSubgraphSchema } from '@apollo/subgraph'; 3 | import { Opts } from '@internal/testing'; 4 | import { parse } from 'graphql'; 5 | import { createYoga } from 'graphql-yoga'; 6 | 7 | const opts = Opts(process.argv); 8 | 9 | const port = opts.getServicePort('upstream_good'); 10 | 11 | createServer( 12 | createYoga({ 13 | schema: buildSubgraphSchema({ 14 | typeDefs: parse(/* GraphQL */ ` 15 | type Query { 16 | foo: String 17 | } 18 | `), 19 | resolvers: { 20 | Query: { 21 | foo() { 22 | console.log('foo on upstreamGood'); 23 | return 'bar'; 24 | }, 25 | }, 26 | }, 27 | }), 28 | }), 29 | ).listen(port, () => { 30 | console.log('Upstream good server running on port ' + port); 31 | }); 32 | -------------------------------------------------------------------------------- /e2e/graphos-polling/services/upstream_stuck.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'node:http'; 2 | import { buildSubgraphSchema } from '@apollo/subgraph'; 3 | import { Opts } from '@internal/testing'; 4 | import { parse } from 'graphql'; 5 | import { createYoga } from 'graphql-yoga'; 6 | 7 | const opts = Opts(process.argv); 8 | const port = opts.getServicePort('upstream_stuck'); 9 | 10 | createServer( 11 | createYoga({ 12 | schema: buildSubgraphSchema({ 13 | typeDefs: parse(/* GraphQL */ ` 14 | type Query { 15 | foo: String 16 | } 17 | `), 18 | resolvers: { 19 | Query: { 20 | foo: () => 21 | new Promise(() => { 22 | console.log('foo on upstreamStuck'); 23 | // never resolves 24 | }), 25 | }, 26 | }, 27 | }), 28 | }), 29 | ).listen(port, () => { 30 | console.log('Upstream stuck server running on port ' + port); 31 | }); 32 | -------------------------------------------------------------------------------- /e2e/graphos/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | -------------------------------------------------------------------------------- /e2e/graphos/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/graphos", 3 | "private": true 4 | } 5 | -------------------------------------------------------------------------------- /e2e/header-propagation/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | 3 | export const gatewayConfig = defineConfig({ 4 | propagateHeaders: { 5 | fromClientToSubgraphs({ request }) { 6 | return { 7 | authorization: request.headers.get('authorization') ?? 'default', 8 | 'session-cookie-id': 9 | request.headers.get('session-cookie-id') ?? 'default', 10 | }; 11 | }, 12 | }, 13 | }); 14 | -------------------------------------------------------------------------------- /e2e/header-propagation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/header-propagation", 3 | "private": true, 4 | "dependencies": { 5 | "graphql": "^16.9.0", 6 | "tslib": "^2.8.1" 7 | }, 8 | "devDependencies": { 9 | "@apollo/server": "^4.12.2", 10 | "@apollo/subgraph": "^2.11.0", 11 | "@types/cors": "^2.8.17", 12 | "@types/express": "^5.0.0", 13 | "cors": "^2.8.5", 14 | "express": "^5.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /e2e/hmac-auth-https/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createInlineSigningKeyProvider, 3 | defineConfig, 4 | } from '@graphql-hive/gateway'; 5 | 6 | export const gatewayConfig = defineConfig({ 7 | hmacSignature: { 8 | secret: 'HMAC_SIGNING_SECRET', 9 | }, 10 | jwt: { 11 | forward: { 12 | payload: true, 13 | token: false, 14 | }, 15 | signingKeyProviders: [createInlineSigningKeyProvider('JWT_SIGNING_SECRET')], 16 | reject: { 17 | missingToken: false, 18 | invalidToken: false, 19 | }, 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /e2e/hmac-auth-https/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | import { Opts } from '@internal/testing'; 6 | 7 | const opts = Opts(process.argv); 8 | 9 | export const composeConfig = defineConfig({ 10 | subgraphs: [ 11 | { 12 | sourceHandler: loadGraphQLHTTPSubgraph('users', { 13 | endpoint: `https://localhost:${opts.getServicePort('users')}/graphql`, 14 | source: './services/users/typeDefs.graphql', 15 | }), 16 | }, 17 | { 18 | sourceHandler: loadGraphQLHTTPSubgraph('comments', { 19 | endpoint: `http://localhost:${opts.getServicePort('comments')}/graphql`, 20 | source: './services/comments/typeDefs.graphql', 21 | }), 22 | }, 23 | ], 24 | }); 25 | -------------------------------------------------------------------------------- /e2e/hmac-auth-https/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/hmac-auth-https", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "generate-users-cert": "openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout ./services/users/key.pem -out ./services/users/cert.pem -subj \"/CN=users_subgraph\" -addext \"subjectAltName=DNS:users_subgraph,DNS:localhost,IP:172.17.0.1,DNS:host.docker.internal\" && cp ./services/users/cert.pem ./users_cert.pem" 7 | }, 8 | "dependencies": { 9 | "@apollo/server": "^4.12.2", 10 | "@apollo/subgraph": "^2.11.0", 11 | "@graphql-hive/gateway": "workspace:^", 12 | "@graphql-mesh/compose-cli": "^1.4.1", 13 | "@graphql-mesh/hmac-upstream-signature": "workspace:^", 14 | "@graphql-mesh/plugin-jwt-auth": "workspace:^", 15 | "graphql": "^16.10.0", 16 | "graphql-yoga": "^5.13.5" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /e2e/hmac-auth-https/services/comments/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend schema 2 | @link( 3 | url: "https://specs.apollo.dev/federation/v2.5" 4 | import: ["@key", "@requiresScopes"] 5 | ) 6 | 7 | type Comment @key(fields: "id") { 8 | id: ID! 9 | text: String! 10 | author: User! 11 | } 12 | 13 | type User @key(fields: "id") { 14 | id: ID! 15 | comments: [Comment!]! @requiresScopes(scopes: [["ReadComments"]]) 16 | } 17 | 18 | type Query { 19 | comments: [Comment] 20 | } 21 | -------------------------------------------------------------------------------- /e2e/hmac-auth-https/services/users/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend schema 2 | @link( 3 | url: "https://specs.apollo.dev/federation/v2.5" 4 | import: ["@key", "@requiresScopes", "@authenticated"] 5 | ) 6 | 7 | type User @key(fields: "id") { 8 | id: ID! 9 | name: String! @requiresScopes(scopes: [["ReadUsersName"]]) 10 | } 11 | 12 | type Query { 13 | me: User @authenticated 14 | users: [User] 15 | user(id: ID!): User 16 | } 17 | -------------------------------------------------------------------------------- /e2e/hoist-and-prefix-transform/hoist-and-prefix-transform.e2e.ts: -------------------------------------------------------------------------------- 1 | import { createTenv } from '@internal/e2e'; 2 | import { expect, it } from 'vitest'; 3 | 4 | const { composeWithMesh, gateway, service, fs } = createTenv(__dirname); 5 | 6 | it('should execute', async () => { 7 | const { output } = await composeWithMesh({ 8 | output: 'graphql', 9 | services: [await service('weather')], 10 | }); 11 | 12 | // expect correct compose 13 | const supergraph = await fs.read(output); 14 | expect(supergraph).toContain('Test_Weather'); 15 | expect(supergraph).toContain('chanceOfRain'); 16 | 17 | const { execute } = await gateway({ supergraph: output }); 18 | await expect( 19 | execute({ 20 | query: /* GraphQL */ ` 21 | { 22 | here { 23 | chanceOfRain 24 | } 25 | } 26 | `, 27 | }), 28 | ).resolves.toEqual({ data: { here: { chanceOfRain: 1 } } }); 29 | }); 30 | -------------------------------------------------------------------------------- /e2e/hoist-and-prefix-transform/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createHoistFieldTransform, 3 | createPrefixTransform, 4 | defineConfig, 5 | loadGraphQLHTTPSubgraph, 6 | } from '@graphql-mesh/compose-cli'; 7 | import { Opts } from '@internal/testing'; 8 | 9 | const opts = Opts(process.argv); 10 | 11 | export const composeConfig = defineConfig({ 12 | subgraphs: [ 13 | { 14 | sourceHandler: loadGraphQLHTTPSubgraph('weather', { 15 | endpoint: `http://localhost:${opts.getServicePort('weather')}/graphql`, 16 | }), 17 | transforms: [ 18 | createPrefixTransform({ 19 | value: 'Test_', 20 | }), 21 | createHoistFieldTransform({ 22 | mapping: [ 23 | { 24 | typeName: 'Test_Weather', 25 | pathConfig: ['rain', 'chance'], 26 | newFieldName: 'chanceOfRain', 27 | }, 28 | ], 29 | }), 30 | ], 31 | }, 32 | ], 33 | }); 34 | -------------------------------------------------------------------------------- /e2e/hoist-and-prefix-transform/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/hoist-and-prefix-transform", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "graphql": "^16.9.0", 7 | "tslib": "^2.8.1" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /e2e/hoist-and-prefix-transform/services/weather.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { Opts } from '@internal/testing'; 3 | import { createSchema, createYoga } from 'graphql-yoga'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | createServer( 8 | createYoga({ 9 | maskedErrors: false, 10 | schema: createSchema({ 11 | typeDefs: /* GraphQL */ ` 12 | type Query { 13 | here: Weather 14 | } 15 | 16 | type Weather { 17 | rain: Rain! 18 | } 19 | 20 | type Rain { 21 | chance: Float! 22 | } 23 | `, 24 | resolvers: { 25 | Query: { 26 | here: () => ({ 27 | rain: { chance: 1 }, 28 | }), 29 | }, 30 | }, 31 | }), 32 | }), 33 | ).listen(opts.getServicePort('weather')); 34 | -------------------------------------------------------------------------------- /e2e/interface-additional-resolvers/additionalTypeDefs/Node.graphql: -------------------------------------------------------------------------------- 1 | extend interface Node { 2 | self: Node! 3 | @resolveTo( 4 | sourceName: "Test" 5 | sourceTypeName: "Query" 6 | sourceFieldName: "node" 7 | sourceArgs: { id: "{root.id}" } 8 | requiredSelectionSet: "{ id }" 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /e2e/interface-additional-resolvers/additionalTypeDefs/User.ts: -------------------------------------------------------------------------------- 1 | export const extraDefs = /* GraphQL */ ` 2 | extend type User implements Node { 3 | self: Node! 4 | } 5 | `; 6 | -------------------------------------------------------------------------------- /e2e/interface-additional-resolvers/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | 3 | export const gatewayConfig = defineConfig({ 4 | additionalTypeDefs: './additionalTypeDefs/*.graphql', 5 | }); 6 | -------------------------------------------------------------------------------- /e2e/interface-additional-resolvers/interface-additional-resolvers.e2e.ts: -------------------------------------------------------------------------------- 1 | import { createTenv } from '@internal/e2e'; 2 | import { expect, it } from 'vitest'; 3 | 4 | const { gateway, service } = createTenv(__dirname); 5 | 6 | it('works', async () => { 7 | const { execute } = await gateway({ 8 | supergraph: { 9 | with: 'mesh', 10 | services: [await service('Test')], 11 | }, 12 | }); 13 | 14 | const result = await execute({ 15 | query: /* GraphQL */ ` 16 | query { 17 | node(id: "1") { 18 | id 19 | ... on User { 20 | name 21 | } 22 | self { 23 | id 24 | ... on User { 25 | name 26 | } 27 | } 28 | } 29 | } 30 | `, 31 | }); 32 | 33 | expect(result.errors).toBeFalsy(); 34 | expect(result.data.node).toEqual({ 35 | id: '1', 36 | name: 'Alice', 37 | self: { 38 | id: '1', 39 | name: 'Alice', 40 | }, 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /e2e/interface-additional-resolvers/interface-additional-resolvers.memtest.ts: -------------------------------------------------------------------------------- 1 | import { createTenv } from '@internal/e2e'; 2 | import { memtest } from '@internal/perf/memtest'; 3 | 4 | const cwd = __dirname; 5 | 6 | const { gateway, service } = createTenv(cwd); 7 | 8 | memtest( 9 | { 10 | cwd, 11 | query: /* GraphQL */ ` 12 | query { 13 | node(id: "1") { 14 | id 15 | ... on User { 16 | name 17 | } 18 | self { 19 | id 20 | ... on User { 21 | name 22 | } 23 | } 24 | } 25 | } 26 | `, 27 | expectedHeavyFrame: (frame) => 28 | // allocates a lot but all is freed confirmed through heap snapshot 29 | frame.name === 'set' && 30 | frame.callstack.some((frame) => frame.name === 'createBatchingExecutor'), 31 | }, 32 | async () => 33 | await gateway({ 34 | supergraph: { 35 | with: 'mesh', 36 | services: [await service('Test')], 37 | }, 38 | }), 39 | ); 40 | -------------------------------------------------------------------------------- /e2e/interface-additional-resolvers/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | import { Opts } from '@internal/testing'; 6 | 7 | const opts = Opts(process.argv); 8 | 9 | export const composeConfig = defineConfig({ 10 | subgraphs: [ 11 | { 12 | sourceHandler: loadGraphQLHTTPSubgraph('Test', { 13 | endpoint: `http://localhost:${opts.getServicePort('Test')}/graphql`, 14 | }), 15 | }, 16 | ], 17 | additionalTypeDefs: './additionalTypeDefs/*', 18 | }); 19 | -------------------------------------------------------------------------------- /e2e/interface-additional-resolvers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/interface-additional-resolvers", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "graphql": "^16.9.0", 7 | "graphql-yoga": "^5.13.5", 8 | "tslib": "^2.8.1" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /e2e/js-config/gateway.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | 3 | export const gatewayConfig = defineConfig({ 4 | additionalResolvers: { 5 | Query: { 6 | hello() { 7 | return 'world'; 8 | }, 9 | }, 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /e2e/js-config/js-config.e2e.ts: -------------------------------------------------------------------------------- 1 | import { createTenv } from '@internal/e2e'; 2 | import { expect, it } from 'vitest'; 3 | 4 | const { gateway } = createTenv(__dirname); 5 | 6 | it('should execute', async () => { 7 | const { execute } = await gateway({ 8 | supergraph: { 9 | with: 'mesh', 10 | }, 11 | }); 12 | await expect(execute({ query: '{ hello }' })).resolves.toMatchInlineSnapshot( 13 | ` 14 | { 15 | "data": { 16 | "hello": "world", 17 | }, 18 | } 19 | `, 20 | ); 21 | }); 22 | -------------------------------------------------------------------------------- /e2e/js-config/mesh.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-mesh/compose-cli'; 2 | import { GraphQLObjectType, GraphQLSchema, GraphQLString } from 'graphql'; 3 | 4 | export const composeConfig = defineConfig({ 5 | subgraphs: [ 6 | { 7 | sourceHandler: () => ({ 8 | name: 'helloworld', 9 | schema$: new GraphQLSchema({ 10 | query: new GraphQLObjectType({ 11 | name: 'Query', 12 | fields: { 13 | hello: { 14 | type: GraphQLString, 15 | resolve: () => 'world', 16 | }, 17 | }, 18 | }), 19 | }), 20 | }), 21 | }, 22 | ], 23 | }); 24 | -------------------------------------------------------------------------------- /e2e/js-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/js-config", 3 | "type": "module", 4 | "private": true, 5 | "dependencies": { 6 | "@graphql-mesh/compose-cli": "^1.4.1", 7 | "graphql": "^16.9.0", 8 | "tslib": "^2.8.1" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /e2e/json-schema-subscriptions/addTodo.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TodoName", 3 | "content": "TodoContent" 4 | } 5 | -------------------------------------------------------------------------------- /e2e/json-schema-subscriptions/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | import useMeshLiveQuery from '@graphql-mesh/plugin-live-query'; 3 | 4 | export const gatewayConfig = defineConfig({ 5 | webhooks: true, 6 | plugins: (ctx) => [ 7 | useMeshLiveQuery({ 8 | ...ctx, 9 | invalidations: [ 10 | { 11 | field: 'Mutation.addTodo', 12 | invalidate: ['Query.todos'], 13 | }, 14 | ], 15 | }), 16 | ], 17 | }); 18 | -------------------------------------------------------------------------------- /e2e/json-schema-subscriptions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/json-schema-subscriptions", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@graphql-mesh/cross-helpers": "^0.4.10", 7 | "@graphql-mesh/plugin-live-query": "^0.104.0", 8 | "@omnigraph/json-schema": "^0.109.5", 9 | "fets": "^0.8.4", 10 | "graphql": "^16.9.0", 11 | "graphql-sse": "^2.5.3", 12 | "tslib": "^2.8.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /e2e/json-schema-subscriptions/todo.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 0, 3 | "name": "TodoName", 4 | "content": "TodoContent" 5 | } 6 | -------------------------------------------------------------------------------- /e2e/json-schema-subscriptions/todos.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 0, 4 | "name": "TodoName", 5 | "content": "TodoContent" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /e2e/manual-transport-def/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | import rest from '@graphql-mesh/transport-rest'; 3 | 4 | export const gatewayConfig = defineConfig({ 5 | transports: { 6 | rest, 7 | http: import('@graphql-mesh/transport-http'), 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /e2e/manual-transport-def/manual-transport-def.e2e.ts: -------------------------------------------------------------------------------- 1 | import { createTenv } from '@internal/e2e'; 2 | import { expect, it } from 'vitest'; 3 | 4 | const { gateway, service } = createTenv(__dirname); 5 | 6 | it('should execute the query', async () => { 7 | const { execute } = await gateway({ 8 | supergraph: { 9 | with: 'mesh', 10 | services: [await service('greetings'), await service('helloer')], 11 | }, 12 | }); 13 | await expect( 14 | execute({ 15 | query: /* GraphQL */ ` 16 | query { 17 | greet(name: "world") { 18 | greeting 19 | } 20 | hello 21 | } 22 | `, 23 | }), 24 | ).resolves.toMatchInlineSnapshot(` 25 | { 26 | "data": { 27 | "greet": { 28 | "greeting": "Hello, world!", 29 | }, 30 | "hello": "world", 31 | }, 32 | } 33 | `); 34 | }); 35 | -------------------------------------------------------------------------------- /e2e/manual-transport-def/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | import { Opts } from '@internal/testing'; 6 | import { loadOpenAPISubgraph } from '@omnigraph/openapi'; 7 | 8 | const opts = Opts(process.argv); 9 | 10 | export const composeConfig = defineConfig({ 11 | subgraphs: [ 12 | { 13 | sourceHandler: loadOpenAPISubgraph('greetings', { 14 | source: `http://localhost:${opts.getServicePort('greetings')}/openapi.json`, 15 | endpoint: `http://localhost:${opts.getServicePort('greetings')}`, 16 | }), 17 | }, 18 | { 19 | sourceHandler: loadGraphQLHTTPSubgraph('helloer', { 20 | endpoint: `http://localhost:${opts.getServicePort('helloer')}/graphql`, 21 | }), 22 | }, 23 | ], 24 | }); 25 | -------------------------------------------------------------------------------- /e2e/manual-transport-def/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/manual-transport-def", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@graphql-mesh/transport-rest": "^0.9.0", 7 | "@omnigraph/openapi": "^0.109.10", 8 | "fets": "^0.8.4", 9 | "graphql": "^16.9.0" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/manual-transport-def/services/greetings.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'node:http'; 2 | import { Opts } from '@internal/testing'; 3 | import { createRouter, Response, Type } from 'fets'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | createServer( 8 | createRouter().route({ 9 | method: 'GET', 10 | operationId: 'greet', 11 | path: '/greet/:name', 12 | schemas: { 13 | request: { 14 | params: Type.Object({ 15 | name: Type.String(), 16 | }), 17 | }, 18 | responses: { 19 | 200: Type.Object({ 20 | greeting: Type.String(), 21 | }), 22 | }, 23 | }, 24 | handler(req) { 25 | return Response.json({ 26 | greeting: `Hello, ${req.params.name}!`, 27 | }); 28 | }, 29 | }), 30 | ).listen(opts.getServicePort('greetings')); 31 | -------------------------------------------------------------------------------- /e2e/manual-transport-def/services/helloer.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { Opts } from '@internal/testing'; 3 | import { createSchema, createYoga } from 'graphql-yoga'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | export const yoga = createYoga({ 8 | schema: createSchema({ 9 | typeDefs: /* GraphQL */ ` 10 | type Query { 11 | hello: String! 12 | } 13 | `, 14 | resolvers: { 15 | Query: { 16 | hello: () => 'world', 17 | }, 18 | }, 19 | }), 20 | }); 21 | 22 | createServer(yoga).listen(opts.getServicePort('helloer', true)); 23 | -------------------------------------------------------------------------------- /e2e/naming-convention-additional-typedefs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/naming-convention-additional-typedefs", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "fets": "^0.8.4", 8 | "graphql": "16.11.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /e2e/naming-convention-additional-typedefs/services/data.ts: -------------------------------------------------------------------------------- 1 | export const books = [ 2 | { 3 | id: '1', 4 | title: 'The Great Gatsby', 5 | author_id: '1', 6 | }, 7 | { 8 | id: '2', 9 | title: 'To Kill a Mockingbird', 10 | author_id: '2', 11 | }, 12 | { 13 | id: '3', 14 | title: '1984', 15 | author_id: '3', 16 | }, 17 | ]; 18 | 19 | export const authors = [ 20 | { 21 | id: '1', 22 | name: 'F. Scott Fitzgerald', 23 | }, 24 | { 25 | id: '2', 26 | name: 'Harper Lee', 27 | }, 28 | { 29 | id: '3', 30 | name: 'George Orwell', 31 | }, 32 | ]; 33 | -------------------------------------------------------------------------------- /e2e/nestjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/nestjs", 3 | "version": "0.0.1", 4 | "type": "module", 5 | "private": true, 6 | "dependencies": { 7 | "@graphql-hive/nestjs": "workspace:^", 8 | "@nestjs/common": "^11.1.2", 9 | "@nestjs/core": "^11.1.2", 10 | "@nestjs/graphql": "^13.0.3", 11 | "@nestjs/platform-express": "^11.1.2", 12 | "file-type": "^21.0.0", 13 | "graphql": "^16.10.0", 14 | "reflect-metadata": "^0.2.2", 15 | "rxjs": "^7.8.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /e2e/nestjs/services/nestjs/app.module.ts: -------------------------------------------------------------------------------- 1 | import { 2 | HiveGatewayDriver, 3 | HiveGatewayDriverConfig, 4 | } from '@graphql-hive/nestjs'; 5 | import { Opts } from '@internal/testing'; 6 | import { Module } from '@nestjs/common'; 7 | import { GraphQLModule } from '@nestjs/graphql'; 8 | 9 | const opts = Opts(process.argv); 10 | const supergraph = opts.get('supergraph', true); 11 | 12 | @Module({ 13 | imports: [ 14 | GraphQLModule.forRoot({ 15 | driver: HiveGatewayDriver, 16 | supergraph, 17 | }), 18 | ], 19 | }) 20 | export class AppModule {} 21 | -------------------------------------------------------------------------------- /e2e/nestjs/services/nestjs/index.ts: -------------------------------------------------------------------------------- 1 | import { Opts } from '@internal/testing'; 2 | import { NestFactory } from '@nestjs/core'; 3 | import { AppModule } from './app.module'; 4 | 5 | const opts = Opts(process.argv); 6 | const port = opts.getServicePort('nestjs', true); 7 | 8 | async function main() { 9 | const app = await NestFactory.create(AppModule); 10 | await app.listen(port); 11 | } 12 | 13 | main().catch((err) => { 14 | console.error(err); 15 | process.exit(1); 16 | }); 17 | -------------------------------------------------------------------------------- /e2e/openapi-additional-resolvers/additionalTypeDefs/apple.graphql: -------------------------------------------------------------------------------- 1 | extend type pageview_project { 2 | apple: String! 3 | } 4 | -------------------------------------------------------------------------------- /e2e/openapi-additional-resolvers/additionalTypeDefs/banana.graphql: -------------------------------------------------------------------------------- 1 | extend type pageview_project { 2 | banana: String 3 | } 4 | -------------------------------------------------------------------------------- /e2e/openapi-additional-resolvers/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | 3 | export const gatewayConfig = defineConfig({ 4 | additionalResolvers: { 5 | pageview_project: { 6 | banana() { 7 | return '🍌'; 8 | }, 9 | apple() { 10 | return '🍎'; 11 | }, 12 | }, 13 | }, 14 | }); 15 | -------------------------------------------------------------------------------- /e2e/openapi-additional-resolvers/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-mesh/compose-cli'; 2 | import { loadOpenAPISubgraph } from '@omnigraph/openapi'; 3 | 4 | export const composeConfig = defineConfig({ 5 | subgraphs: [ 6 | { 7 | sourceHandler: loadOpenAPISubgraph('Wiki', { 8 | source: 9 | 'https://api.apis.guru/v2/specs/wikimedia.org/1.0.0/swagger.yaml', 10 | endpoint: 'https://wikimedia.org/api/rest_v1', 11 | }), 12 | }, 13 | ], 14 | additionalTypeDefs: './additionalTypeDefs/*.graphql', 15 | }); 16 | -------------------------------------------------------------------------------- /e2e/openapi-additional-resolvers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/openapi-additional-resolvers", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "graphql": "^16.9.0", 8 | "moment": "^2.30.1", 9 | "tslib": "^2.8.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/openapi-arg-rename/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | camelCase, 3 | createNamingConventionTransform, 4 | createRenameTransform, 5 | defineConfig, 6 | } from '@graphql-mesh/compose-cli'; 7 | import { Opts } from '@internal/testing'; 8 | import { loadOpenAPISubgraph } from '@omnigraph/openapi'; 9 | 10 | const opts = Opts(process.argv); 11 | 12 | export const composeConfig = defineConfig({ 13 | subgraphs: [ 14 | { 15 | sourceHandler: loadOpenAPISubgraph('Wiki', { 16 | source: './openapi.json', 17 | endpoint: `http://localhost:${opts.getServicePort('Wiki')}`, 18 | }), 19 | transforms: [ 20 | createNamingConventionTransform({ 21 | fieldNames: camelCase, 22 | }), 23 | createRenameTransform({ 24 | argRenamer: ({ argName, fieldName }) => { 25 | if (fieldName === 'postBad' && argName === 'input') { 26 | return 'requestBody'; 27 | } 28 | 29 | return argName; 30 | }, 31 | }), 32 | ], 33 | }, 34 | ], 35 | }); 36 | -------------------------------------------------------------------------------- /e2e/openapi-arg-rename/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/openapi-arg-rename", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "graphql": "16.11.0", 8 | "moment": "2.30.1", 9 | "tslib": "^2.8.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/openapi-arg-rename/services/Wiki.ts: -------------------------------------------------------------------------------- 1 | import http from 'node:http'; 2 | import { Opts } from '@internal/testing'; 3 | 4 | const opts = Opts(process.argv); 5 | 6 | const server = http.createServer((req, res) => { 7 | if (req.url?.endsWith('good')) { 8 | res.setHeader('content-type', 'application/json'); 9 | res.end(JSON.stringify({ apple: 'good' })); 10 | return; 11 | } 12 | if (req.url?.endsWith('bad')) { 13 | res.setHeader('content-type', 'application/json'); 14 | res.end(JSON.stringify({ apple: 'bad' })); 15 | return; 16 | } 17 | res.writeHead(404); 18 | res.end(); 19 | return; 20 | }); 21 | 22 | server.listen(opts.getServicePort('Wiki')); 23 | -------------------------------------------------------------------------------- /e2e/openapi-javascript-wiki/gateway.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gateway_e2e 2 | 3 | RUN npm i moment 4 | -------------------------------------------------------------------------------- /e2e/openapi-javascript-wiki/gateway_bun.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gateway_e2e-bun 2 | 3 | RUN bun i moment 4 | -------------------------------------------------------------------------------- /e2e/openapi-javascript-wiki/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-mesh/compose-cli'; 2 | import { loadOpenAPISubgraph } from '@omnigraph/openapi'; 3 | 4 | export const composeConfig = defineConfig({ 5 | subgraphs: [ 6 | { 7 | sourceHandler: loadOpenAPISubgraph('Wiki', { 8 | source: 9 | 'https://api.apis.guru/v2/specs/wikimedia.org/1.0.0/swagger.yaml', 10 | endpoint: 'https://wikimedia.org/api/rest_v1', 11 | ignoreErrorResponses: true, 12 | }), 13 | }, 14 | ], 15 | additionalTypeDefs: /* GraphQL */ ` 16 | extend type Query { 17 | viewsInPastMonth(project: String!): Int! 18 | } 19 | `, 20 | }); 21 | -------------------------------------------------------------------------------- /e2e/openapi-javascript-wiki/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/openapi-javascript-wiki", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "graphql": "^16.9.0", 8 | "moment": "^2.30.1", 9 | "tslib": "^2.8.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/openapi-min-length/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-mesh/compose-cli'; 2 | import { loadOpenAPISubgraph } from '@omnigraph/openapi'; 3 | 4 | export const composeConfig = defineConfig({ 5 | subgraphs: [ 6 | { 7 | sourceHandler: loadOpenAPISubgraph('Wiki', { 8 | source: './openapi.json', 9 | endpoint: 'https://api.chucknorris.io', 10 | }), 11 | }, 12 | ], 13 | }); 14 | -------------------------------------------------------------------------------- /e2e/openapi-min-length/openapi-min-length.e2e.ts: -------------------------------------------------------------------------------- 1 | import { createTenv } from '@internal/e2e'; 2 | import { expect, it } from 'vitest'; 3 | 4 | const { gateway } = createTenv(__dirname); 5 | 6 | it('should execute Metrics with banana', async () => { 7 | const { execute } = await gateway({ supergraph: { with: 'mesh' } }); 8 | await expect( 9 | execute({ 10 | query: /* GraphQL */ ` 11 | query Categories { 12 | jokes_categories 13 | } 14 | `, 15 | }), 16 | ).resolves.toMatchInlineSnapshot(` 17 | { 18 | "data": { 19 | "jokes_categories": [ 20 | "animal", 21 | "career", 22 | "celebrity", 23 | "dev", 24 | "explicit", 25 | "fashion", 26 | "food", 27 | "history", 28 | "money", 29 | "movie", 30 | "music", 31 | "political", 32 | "religion", 33 | "science", 34 | "sport", 35 | "travel", 36 | ], 37 | }, 38 | } 39 | `); 40 | }); 41 | -------------------------------------------------------------------------------- /e2e/openapi-min-length/openapi.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.1", 3 | "info": { 4 | "title": "Chuck Norris v1", 5 | "version": "1" 6 | }, 7 | "paths": { 8 | "/jokes/categories": { 9 | "get": { 10 | "responses": { 11 | "200": { 12 | "description": "Success", 13 | "content": { 14 | "application/json": { 15 | "schema": { 16 | "type": "array", 17 | "items": { 18 | "$ref": "#/components/schemas/Category" 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } 25 | } 26 | } 27 | }, 28 | "components": { 29 | "schemas": { 30 | "Category": { 31 | "type": "string", 32 | "maxLength": 100 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /e2e/openapi-min-length/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/openapi-min-length", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "graphql": "^16.9.0", 8 | "moment": "^2.30.1", 9 | "tslib": "^2.8.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/openapi-naming-convention/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createNamingConventionTransform, 3 | defineConfig as defineComposeConfig, 4 | upperCase, 5 | } from '@graphql-mesh/compose-cli'; 6 | import { loadOpenAPISubgraph } from '@omnigraph/openapi'; 7 | 8 | export const composeConfig = defineComposeConfig({ 9 | subgraphs: [ 10 | { 11 | sourceHandler: loadOpenAPISubgraph('Wiki', { 12 | source: './openapi.json', 13 | endpoint: 'https://api.chucknorris.io', 14 | }), 15 | transforms: [ 16 | createNamingConventionTransform({ 17 | enumValues: upperCase, 18 | }), 19 | ], 20 | }, 21 | ], 22 | }); 23 | -------------------------------------------------------------------------------- /e2e/openapi-naming-convention/openapi-naming-convention.e2e.ts: -------------------------------------------------------------------------------- 1 | import { createTenv } from '@internal/e2e'; 2 | import { expect, it } from 'vitest'; 3 | 4 | const { gateway } = createTenv(__dirname); 5 | 6 | it('should execute Metrics with banana', async () => { 7 | const { execute } = await gateway({ supergraph: { with: 'mesh' } }); 8 | await expect( 9 | execute({ 10 | query: /* GraphQL */ ` 11 | query Categories { 12 | jokes_categories 13 | } 14 | `, 15 | }), 16 | ).resolves.toMatchInlineSnapshot(` 17 | { 18 | "data": { 19 | "jokes_categories": [ 20 | "ANIMAL", 21 | "CAREER", 22 | "CELEBRITY", 23 | "DEV", 24 | "EXPLICIT", 25 | "FASHION", 26 | "FOOD", 27 | "HISTORY", 28 | "MONEY", 29 | "MOVIE", 30 | "MUSIC", 31 | "POLITICAL", 32 | "RELIGION", 33 | "SCIENCE", 34 | "SPORT", 35 | "TRAVEL", 36 | ], 37 | }, 38 | } 39 | `); 40 | }); 41 | -------------------------------------------------------------------------------- /e2e/openapi-naming-convention/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/openapi-naming-convention", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "graphql": "^16.9.0", 8 | "moment": "^2.30.1", 9 | "tslib": "^2.8.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/openapi-prune/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { createPruneTransform, defineConfig } from '@graphql-mesh/compose-cli'; 2 | import { Opts } from '@internal/testing'; 3 | import { loadOpenAPISubgraph } from '@omnigraph/openapi'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | export const composeConfig = defineConfig({ 8 | subgraphs: [ 9 | { 10 | sourceHandler: loadOpenAPISubgraph('Wiki', { 11 | source: './openapi.json', 12 | endpoint: 'http://localhost:' + opts.getServicePort('Wiki'), 13 | }), 14 | transforms: [createPruneTransform()], 15 | }, 16 | ], 17 | }); 18 | -------------------------------------------------------------------------------- /e2e/openapi-prune/openapi-prune.e2e.ts: -------------------------------------------------------------------------------- 1 | import { createTenv } from '@internal/e2e'; 2 | import { expect, it } from 'vitest'; 3 | 4 | const { gateway, service } = createTenv(__dirname); 5 | 6 | it('should work when pruned', async () => { 7 | const { execute } = await gateway({ 8 | supergraph: { 9 | with: 'mesh', 10 | services: [await service('Wiki')], 11 | }, 12 | }); 13 | await expect( 14 | execute({ 15 | query: /* GraphQL */ ` 16 | mutation Main { 17 | post_main(input: { banana: true }) { 18 | apple 19 | } 20 | } 21 | `, 22 | }), 23 | ).resolves.toMatchInlineSnapshot(` 24 | { 25 | "data": { 26 | "post_main": [ 27 | { 28 | "apple": "correct", 29 | }, 30 | ], 31 | }, 32 | } 33 | `); 34 | }); 35 | -------------------------------------------------------------------------------- /e2e/openapi-prune/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/openapi-prune", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "graphql": "^16.9.0", 8 | "moment": "^2.30.1", 9 | "tslib": "^2.8.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/openapi-prune/services/Wiki.ts: -------------------------------------------------------------------------------- 1 | import http from 'node:http'; 2 | import { Opts } from '@internal/testing'; 3 | 4 | const opts = Opts(process.argv); 5 | 6 | const server = http.createServer((req, res) => { 7 | const u = new URL(req.url!, 'http://localhost'); 8 | if (u.pathname === '/main') { 9 | if (req.method === 'POST') { 10 | return res 11 | .setHeader('content-type', 'application/json') 12 | .end(JSON.stringify({ apple: 'correct' })); 13 | } else { 14 | return res 15 | .setHeader('content-type', 'application/json') 16 | .end(JSON.stringify({ apple: 'bad' })); 17 | } 18 | } 19 | return res.writeHead(404).end(); 20 | }); 21 | 22 | server.listen(opts.getServicePort('Wiki')); 23 | -------------------------------------------------------------------------------- /e2e/openapi-subgraph/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/openapi-subgraph", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "fets": "^0.8.4", 8 | "graphql": "^16.9.0", 9 | "tslib": "^2.8.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/openapi-subgraph/services/GQL.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'node:http'; 2 | import { Opts } from '@internal/testing'; 3 | import { createSchema, createYoga } from 'graphql-yoga'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | const PORT = opts.getServicePort('GQL'); 8 | 9 | createServer( 10 | createYoga({ 11 | schema: createSchema({ 12 | typeDefs: /* GraphQL */ ` 13 | type Query { 14 | books: [Book!]! 15 | } 16 | 17 | type Book { 18 | id: ID! 19 | title: String! 20 | } 21 | `, 22 | resolvers: { 23 | Query: { 24 | books() { 25 | return [ 26 | { id: '1', title: 'Book 1' }, 27 | { id: '2', title: 'Book 2' }, 28 | { id: '3', title: 'Book 3' }, 29 | ]; 30 | }, 31 | }, 32 | }, 33 | }), 34 | }), 35 | ).listen(PORT, () => { 36 | console.log(`🚀 Server ready at http://localhost:${PORT}`); 37 | }); 38 | -------------------------------------------------------------------------------- /e2e/openapi-subscriptions/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | 3 | export const gatewayConfig = defineConfig({ 4 | webhooks: true, 5 | }); 6 | -------------------------------------------------------------------------------- /e2e/openapi-subscriptions/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-mesh/compose-cli'; 2 | import { Opts } from '@internal/testing'; 3 | import { loadOpenAPISubgraph } from '@omnigraph/openapi'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | export const composeConfig = defineConfig({ 8 | subgraphs: [ 9 | { 10 | sourceHandler: loadOpenAPISubgraph('OpenAPICallbackExample', { 11 | source: './services/api/openapi.yml', 12 | endpoint: `http://localhost:${opts.getServicePort('api')}`, 13 | }), 14 | }, 15 | ], 16 | }); 17 | -------------------------------------------------------------------------------- /e2e/openapi-subscriptions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/openapi-subscriptions", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "fets": "^0.8.4", 8 | "graphql": "^16.9.0", 9 | "graphql-sse": "^2.5.3", 10 | "tslib": "^2.8.1", 11 | "url-join": "^5.0.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /e2e/opentelemetry/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/opentelemetry", 3 | "private": true, 4 | "dependencies": { 5 | "@apollo/server": "^4.12.2", 6 | "@apollo/subgraph": "^2.11.0", 7 | "@graphql-mesh/compose-cli": "^1.4.1", 8 | "graphql": "^16.8.1", 9 | "graphql-yoga": "^5.13.5", 10 | "tslib": "^2.8.1" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /e2e/operation-field-permissions/gateway.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gateway_e2e 2 | 3 | RUN npm i @envelop/operation-field-permissions 4 | -------------------------------------------------------------------------------- /e2e/operation-field-permissions/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { useOperationFieldPermissions } from '@envelop/operation-field-permissions'; 2 | import { defineConfig, GatewayContext } from '@graphql-hive/gateway'; 3 | 4 | export const gatewayConfig = defineConfig({ 5 | plugins: () => [ 6 | useOperationFieldPermissions({ 7 | getPermissions(ctx: GatewayContext) { 8 | const auth = ctx.request.headers.get('authorization'); 9 | if ( 10 | auth === 11 | 'Bearer TOKEN' /** NOTE: proper token validity check goes here */ 12 | ) { 13 | // allow all fields 14 | return new Set(['*']); 15 | } 16 | // allow only introspection 17 | return new Set(['Query.registrationOpen']); 18 | }, 19 | }) as any, // TODO: fix generic in envelop 20 | ], 21 | }); 22 | -------------------------------------------------------------------------------- /e2e/operation-field-permissions/gateway_bun.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gateway_e2e-bun 2 | 3 | RUN bun i @envelop/operation-field-permissions 4 | -------------------------------------------------------------------------------- /e2e/operation-field-permissions/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | import { Opts } from '@internal/testing'; 6 | 7 | const opts = Opts(process.argv); 8 | 9 | export const composeConfig = defineConfig({ 10 | subgraphs: [ 11 | { 12 | sourceHandler: loadGraphQLHTTPSubgraph('users', { 13 | endpoint: `http://localhost:${opts.getServicePort('users')}/graphql`, 14 | }), 15 | }, 16 | ], 17 | }); 18 | -------------------------------------------------------------------------------- /e2e/operation-field-permissions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/operation-field-permissions", 3 | "private": true, 4 | "dependencies": { 5 | "@envelop/core": "^5.2.3", 6 | "@envelop/operation-field-permissions": "^7.0.0", 7 | "@graphql-mesh/compose-cli": "^1.4.1", 8 | "graphql": "^16.10.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /e2e/operation-field-permissions/services/users.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { Opts } from '@internal/testing'; 3 | import { createSchema, createYoga } from 'graphql-yoga'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | createServer( 8 | createYoga({ 9 | maskedErrors: false, 10 | schema: createSchema({ 11 | typeDefs: /* GraphQL */ ` 12 | type Query { 13 | registrationOpen: Boolean! 14 | me: User! 15 | } 16 | type User { 17 | name: String! 18 | } 19 | `, 20 | resolvers: { 21 | Query: { 22 | registrationOpen: () => false, 23 | me: () => ({ name: 'John' }), 24 | }, 25 | }, 26 | }), 27 | }), 28 | ).listen(opts.getServicePort('users')); 29 | -------------------------------------------------------------------------------- /e2e/polling/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { defineConfig } from '@graphql-hive/gateway'; 3 | 4 | const SUPERGRAPH_PATH = process.env['SUPERGRAPH_PATH'] || 'supergraph.graphql'; 5 | 6 | export const gatewayConfig = defineConfig({ 7 | supergraph: async (): Promise => { 8 | console.log(`[${new Date().toISOString()}]`, 'Reading ' + SUPERGRAPH_PATH); 9 | return fs.promises.readFile(SUPERGRAPH_PATH, 'utf8'); 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /e2e/polling/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | import { Opts } from '@internal/testing'; 6 | 7 | const opts = Opts(process.argv); 8 | const SERVICE_PORT = opts.getServicePort('Graph'); 9 | 10 | export const composeConfig = defineConfig({ 11 | subgraphs: [ 12 | { 13 | sourceHandler: loadGraphQLHTTPSubgraph('Graph', { 14 | endpoint: `http://localhost:${SERVICE_PORT}/graphql`, 15 | source: './services/Graph.graphql', 16 | operationHeaders: { 17 | Authorization: "{context.headers['authorization']}", 18 | }, 19 | }), 20 | }, 21 | ], 22 | }); 23 | -------------------------------------------------------------------------------- /e2e/polling/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/polling", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "express": "^5.0.0", 7 | "graphql": "^16.10.0", 8 | "graphql-yoga": "^5.13.5" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /e2e/polling/services/Graph.graphql: -------------------------------------------------------------------------------- 1 | type Query { 2 | hello: String 3 | } 4 | -------------------------------------------------------------------------------- /e2e/polling/services/Graph.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { Opts } from '@internal/testing'; 4 | import express from 'express'; 5 | import { createSchema, createYoga } from 'graphql-yoga'; 6 | 7 | const app = express(); 8 | const opts = Opts(process.argv); 9 | const port = opts.getServicePort('Graph'); 10 | 11 | const schemaPath = path.join(__dirname, 'Graph.graphql'); 12 | const schemaContent = fs.readFileSync(schemaPath, 'utf8'); 13 | 14 | app.use( 15 | '/graphql', 16 | createYoga({ 17 | schema: createSchema({ 18 | typeDefs: schemaContent, 19 | resolvers: { 20 | Query: { 21 | hello: () => { 22 | return new Promise((resolve) => { 23 | setTimeout(() => { 24 | resolve('Hello world!'); 25 | }, 20_000); 26 | }); 27 | }, 28 | }, 29 | }, 30 | }), 31 | }), 32 | ); 33 | 34 | app.listen(port, () => { 35 | console.log(`Server is running on http://localhost:${port}/graphql`); 36 | }); 37 | -------------------------------------------------------------------------------- /e2e/programmatic-batching/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-mesh/compose-cli'; 2 | import { Opts } from '@internal/testing'; 3 | import { loadOpenAPISubgraph } from '@omnigraph/openapi'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | export const composeConfig = defineConfig({ 8 | subgraphs: [ 9 | { 10 | sourceHandler: loadOpenAPISubgraph('API', { 11 | source: `http://localhost:${opts.getServicePort('api')}/openapi.json`, 12 | endpoint: `http://localhost:${opts.getServicePort('api')}`, 13 | ignoreErrorResponses: true, 14 | }), 15 | }, 16 | ], 17 | additionalTypeDefs: /* GraphQL */ ` 18 | extend type Query { 19 | user(id: Float!): User 20 | } 21 | `, 22 | }); 23 | -------------------------------------------------------------------------------- /e2e/programmatic-batching/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/programmatic-batching-example", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "fets": "^0.8.4", 8 | "graphql": "16.11.0", 9 | "tslib": "^2.8.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/programmatic-batching/programmatic-batching.e2e.ts: -------------------------------------------------------------------------------- 1 | import { createTenv } from '@internal/e2e'; 2 | import { expect, it } from 'vitest'; 3 | 4 | const { service, gateway } = createTenv(__dirname); 5 | 6 | it('should execute', async () => { 7 | const { execute } = await gateway({ 8 | supergraph: { 9 | with: 'mesh', 10 | services: [await service('api')], 11 | }, 12 | }); 13 | await expect( 14 | execute({ 15 | query: /* GraphQL */ ` 16 | fragment UserF on User { 17 | id 18 | name 19 | } 20 | query User { 21 | john: user(id: 1) { 22 | ...UserF 23 | } 24 | jane: user(id: 2) { 25 | ...UserF 26 | } 27 | } 28 | `, 29 | }), 30 | ).resolves.toMatchInlineSnapshot(` 31 | { 32 | "data": { 33 | "jane": { 34 | "id": 2, 35 | "name": "Jane Doe", 36 | }, 37 | "john": { 38 | "id": 1, 39 | "name": "John Doe", 40 | }, 41 | }, 42 | } 43 | `); 44 | }); 45 | -------------------------------------------------------------------------------- /e2e/programmatic-batching/programmatic-batching.memtest.ts: -------------------------------------------------------------------------------- 1 | import { createTenv } from '@internal/e2e'; 2 | import { memtest } from '@internal/perf/memtest'; 3 | 4 | const cwd = __dirname; 5 | 6 | const { service, gateway } = createTenv(cwd); 7 | 8 | memtest( 9 | { 10 | cwd, 11 | query: /* GraphQL */ ` 12 | fragment UserF on User { 13 | id 14 | name 15 | } 16 | query User { 17 | john: user(id: 1) { 18 | ...UserF 19 | } 20 | jane: user(id: 2) { 21 | ...UserF 22 | } 23 | } 24 | `, 25 | }, 26 | async () => 27 | gateway({ 28 | supergraph: { 29 | with: 'mesh', 30 | services: [await service('api')], 31 | }, 32 | }), 33 | ); 34 | -------------------------------------------------------------------------------- /e2e/regular-subgraph/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/regular-subgraph", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-hive/gateway": "workspace:*", 6 | "@graphql-mesh/compose-cli": "^1.4.8", 7 | "graphql": "16.11.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /e2e/retry-timeout/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, useDeduplicateRequest } from '@graphql-hive/gateway'; 2 | 3 | let i = 0; 4 | export const gatewayConfig = defineConfig({ 5 | upstreamRetry: { 6 | maxRetries: 4, 7 | }, 8 | upstreamTimeout: 300, 9 | plugins(ctx) { 10 | return [ 11 | ...(process.env['DEDUPLICATE_REQUEST'] ? [useDeduplicateRequest()] : []), 12 | { 13 | onFetch() { 14 | i++; 15 | ctx.logger.info(`[FETCHING] #${i}`); 16 | }, 17 | }, 18 | ]; 19 | }, 20 | }); 21 | -------------------------------------------------------------------------------- /e2e/retry-timeout/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | import { Opts } from '@internal/testing'; 6 | import { loadOpenAPISubgraph } from '@omnigraph/openapi'; 7 | 8 | const opts = Opts(process.argv); 9 | 10 | const oaiEndpoint = `http://localhost:${opts.getServicePort('oai-flakey')}`; 11 | const gqlEndpoint = `http://localhost:${opts.getServicePort('gql-flakey')}/graphql`; 12 | 13 | export const composeConfig = defineConfig({ 14 | subgraphs: [ 15 | { 16 | sourceHandler: loadOpenAPISubgraph('oai-flakey', { 17 | source: `${oaiEndpoint}/openapi.json`, 18 | endpoint: oaiEndpoint, 19 | }), 20 | }, 21 | { 22 | sourceHandler: loadGraphQLHTTPSubgraph('gql-flakey', { 23 | endpoint: gqlEndpoint, 24 | }), 25 | }, 26 | ], 27 | }); 28 | -------------------------------------------------------------------------------- /e2e/retry-timeout/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/retry-timeout", 3 | "private": true, 4 | "dependencies": { 5 | "@apollo/subgraph": "^2.11.0", 6 | "@graphql-hive/gateway": "workspace:*", 7 | "graphql": "16.11.0", 8 | "graphql-yoga": "^5.13.5", 9 | "tslib": "^2.8.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/self-hosting-hive/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | import { boolEnv, Opts } from '@internal/testing'; 3 | 4 | const opts = Opts(process.argv); 5 | const selfHostingHost = String(process.env['E2E_GATEWAY_RUNNER']).includes( 6 | 'docker', 7 | ) 8 | ? boolEnv('CI') 9 | ? '172.17.0.1' 10 | : 'host.docker.internal' 11 | : 'localhost'; 12 | const selfHostingPort = opts.getServicePort('selfHostingHive'); 13 | 14 | export const gatewayConfig = defineConfig({ 15 | reporting: { 16 | type: 'hive', 17 | agent: { 18 | maxRetries: 1, 19 | maxSize: 1, 20 | timeout: 200, 21 | }, 22 | selfHosting: { 23 | applicationUrl: `http://${selfHostingHost}:${selfHostingPort}`, 24 | graphqlEndpoint: `http://${selfHostingHost}:${selfHostingPort}/graphql`, 25 | usageEndpoint: `http://${selfHostingHost}:${selfHostingPort}/usage`, 26 | }, 27 | }, 28 | }); 29 | -------------------------------------------------------------------------------- /e2e/self-hosting-hive/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/self-hosting-hive", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-hive/gateway": "workspace:*", 6 | "graphql": "16.11.0" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /e2e/self-hosting-hive/services/selfHostingHive.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { Opts } from '@internal/testing'; 3 | 4 | const opts = Opts(process.argv); 5 | const selfHostingPort = opts.getServicePort('selfHostingHive'); 6 | 7 | // Echo server 8 | 9 | createServer((req, res) => { 10 | function echo(msg: string) { 11 | process.stdout.write(msg); 12 | res.write(msg); 13 | } 14 | res.writeHead(200, req.headers); 15 | echo(`${req.method} ${req.url}\n`); 16 | echo(`headers: ${JSON.stringify(req.headers)}\n`); 17 | req.on('data', (chunk) => { 18 | echo(chunk.toString('utf8')); 19 | }); 20 | req.once('end', () => { 21 | res.end(); 22 | }); 23 | }).listen(selfHostingPort, () => { 24 | process.stderr.write( 25 | `Echo server listening on http://localhost:${selfHostingPort}\n`, 26 | ); 27 | }); 28 | -------------------------------------------------------------------------------- /e2e/subscriptions-cancellation/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | 3 | export const gatewayConfig = defineConfig({ 4 | plugins() { 5 | return [ 6 | { 7 | onSubgraphExecute: 8 | () => 9 | ({ result }) => { 10 | if (Symbol.asyncIterator in result) { 11 | process.stdout.write('__ITERABLE_GW__'); 12 | return { 13 | onNext: () => { 14 | process.stdout.write('__NEXT_GW__'); 15 | }, 16 | onEnd: () => { 17 | process.stdout.write('__END_GW__'); 18 | }, 19 | }; 20 | } 21 | return void 0; 22 | }, 23 | }, 24 | ]; 25 | }, 26 | }); 27 | -------------------------------------------------------------------------------- /e2e/subscriptions-cancellation/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | import { Opts } from '@internal/testing'; 6 | 7 | const opts = Opts(process.argv); 8 | 9 | export const composeConfig = defineConfig({ 10 | subgraphs: [ 11 | { 12 | sourceHandler: loadGraphQLHTTPSubgraph('stream', { 13 | endpoint: `http://localhost:${opts.getServicePort('stream')}/graphql`, 14 | }), 15 | }, 16 | ], 17 | }); 18 | -------------------------------------------------------------------------------- /e2e/subscriptions-cancellation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/subscriptions-cancellation", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "graphql": "^16.9.0", 7 | "graphql-sse": "^2.5.3", 8 | "tslib": "^2.8.1" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /e2e/subscriptions-data-other-subgraph/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/subscriptions-data-other-subgraph", 3 | "private": true, 4 | "dependencies": { 5 | "@apollo/subgraph": "^2.11.0", 6 | "graphql": "^16.9.0", 7 | "graphql-sse": "^2.5.3" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /e2e/subscriptions-with-transforms/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createPrefixTransform, 3 | defineConfig, 4 | loadGraphQLHTTPSubgraph, 5 | } from '@graphql-mesh/compose-cli'; 6 | import { Opts } from '@internal/testing'; 7 | 8 | const opts = Opts(process.argv); 9 | 10 | export const composeConfig = defineConfig({ 11 | subgraphs: [ 12 | { 13 | sourceHandler: loadGraphQLHTTPSubgraph('my-subgraph', { 14 | endpoint: `http://localhost:${opts.getServicePort('my-subgraph')}/graphql`, 15 | source: './services/my-subgraph/schema.graphql', 16 | }), 17 | transforms: [ 18 | createPrefixTransform({ 19 | value: 'test_', 20 | includeRootOperations: true, 21 | }), 22 | ], 23 | }, 24 | ], 25 | }); 26 | -------------------------------------------------------------------------------- /e2e/subscriptions-with-transforms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/subscriptions-with-transforms", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "graphql": "16.11.0", 7 | "graphql-sse": "^2.5.3", 8 | "graphql-yoga": "^5.13.5", 9 | "tslib": "^2.8.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/subscriptions-with-transforms/services/my-subgraph/schema.graphql: -------------------------------------------------------------------------------- 1 | type Query { 2 | hello: String 3 | } 4 | 5 | type Subscription { 6 | countdown(from: Int!): Int! 7 | } 8 | -------------------------------------------------------------------------------- /e2e/supergraph-file-watcher/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | import { Opts } from '@internal/testing'; 6 | 7 | const opts = Opts(process.argv); 8 | 9 | export const composeConfig = defineConfig({ 10 | subgraphs: [ 11 | process.env['USE_B'] 12 | ? { 13 | sourceHandler: loadGraphQLHTTPSubgraph('b', { 14 | endpoint: `http://localhost:${opts.getServicePort('b')}/graphql`, 15 | }), 16 | } 17 | : { 18 | sourceHandler: loadGraphQLHTTPSubgraph('a', { 19 | endpoint: `http://localhost:${opts.getServicePort('a')}/graphql`, 20 | }), 21 | }, 22 | ], 23 | }); 24 | -------------------------------------------------------------------------------- /e2e/supergraph-file-watcher/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/supergraph-file-watcher", 3 | "private": true 4 | } 5 | -------------------------------------------------------------------------------- /e2e/supergraph-file-watcher/services/a.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { Opts } from '@internal/testing'; 3 | import { createSchema, createYoga } from 'graphql-yoga'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | createServer( 8 | createYoga({ 9 | maskedErrors: false, 10 | schema: createSchema({ 11 | typeDefs: /* GraphQL */ ` 12 | type Query { 13 | a: String! 14 | } 15 | `, 16 | resolvers: { 17 | Query: { 18 | a: () => 'hello from a', 19 | }, 20 | }, 21 | }), 22 | }), 23 | ).listen(opts.getServicePort('a')); 24 | -------------------------------------------------------------------------------- /e2e/supergraph-file-watcher/services/b.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { Opts } from '@internal/testing'; 3 | import { createSchema, createYoga } from 'graphql-yoga'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | createServer( 8 | createYoga({ 9 | maskedErrors: false, 10 | schema: createSchema({ 11 | typeDefs: /* GraphQL */ ` 12 | type Query { 13 | b: String! 14 | } 15 | `, 16 | resolvers: { 17 | Query: { 18 | b: () => 'hello from b', 19 | }, 20 | }, 21 | }), 22 | }), 23 | ).listen(opts.getServicePort('b')); 24 | -------------------------------------------------------------------------------- /e2e/supergraph-url/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/supergraph-url", 3 | "private": true, 4 | "dependencies": { 5 | "graphql": "^16.9.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /e2e/supergraph-url/services/cdn.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { Opts } from '@internal/testing'; 3 | 4 | const port = Opts(process.argv).getServicePort('cdn', true); 5 | 6 | createServer((_req, res) => { 7 | res.setHeader('content-type', 'application/graphql'); 8 | res.end(/* GraphQL */ ` 9 | type Query { 10 | hello: String! 11 | } 12 | `); 13 | }).listen(port, () => { 14 | console.log(`CDN service listening on http://localhost:${port}`); 15 | }); 16 | -------------------------------------------------------------------------------- /e2e/top-level-await/gateway.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | 3 | // top level await 4 | await Promise.resolve(); 5 | 6 | export const gatewayConfig = defineConfig({}); 7 | -------------------------------------------------------------------------------- /e2e/top-level-await/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/top-level-await", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "graphql": "^16.9.0", 7 | "tslib": "^2.8.1" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /e2e/top-level-await/top-level-await.e2e.ts: -------------------------------------------------------------------------------- 1 | import { createTenv } from '@internal/e2e'; 2 | import { fetch } from '@whatwg-node/fetch'; 3 | import { expect, it } from 'vitest'; 4 | 5 | const { gateway, fs } = createTenv(__dirname); 6 | 7 | it('should start gateway', async () => { 8 | const proc = await gateway({ 9 | supergraph: await fs.tempfile( 10 | 'supergraph.graphql', 11 | 'type Query { hello: String }', 12 | ), 13 | }); 14 | const res = await fetch(`http://0.0.0.0:${proc.port}/healthcheck`); 15 | expect(res.ok).toBeTruthy(); 16 | }); 17 | -------------------------------------------------------------------------------- /e2e/tsconfig-paths/folder/hck.ts: -------------------------------------------------------------------------------- 1 | export const healthCheckEndpoint = 'helt'; 2 | -------------------------------------------------------------------------------- /e2e/tsconfig-paths/gateway.config.ts: -------------------------------------------------------------------------------- 1 | // @ts-expect-error 2 | import { healthCheckEndpoint } from '@e2e/tsconfig-paths/hck'; 3 | import { defineConfig } from '@graphql-hive/gateway'; 4 | 5 | export const gatewayConfig = defineConfig({ 6 | healthCheckEndpoint, 7 | }); 8 | -------------------------------------------------------------------------------- /e2e/tsconfig-paths/tsconfig-paths.tsconfig.json: -------------------------------------------------------------------------------- 1 | // we use jsconfig.json because tsx picks up tsconfig.json and we want to make sure Mesh runtime does it instead 2 | { 3 | "compilerOptions": { 4 | "paths": { 5 | "@e2e/tsconfig-paths/*": ["./folder/*"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /e2e/type-merging-batching/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@e2e/type-merging-batching", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "graphql": "^16.9.0", 7 | "graphql-yoga": "^5.13.5", 8 | "tslib": "^2.8.1" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | > [!CAUTION] 2 | > These examples are auto-generated using the [e2e](/e2e) tests, do NOT modify them directly! 3 | -------------------------------------------------------------------------------- /examples/apq-subgraphs/.codesandbox/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "setupTasks": [ 3 | { 4 | "name": "Install", 5 | "command": "npm i" 6 | }, 7 | { 8 | "name": "Start service greetings", 9 | "command": "nohup npm run service:greetings &> service-greetings.out &" 10 | }, 11 | { 12 | "name": "Wait for service greetings", 13 | "command": "curl --retry-connrefused --retry 10 --retry-delay 3 http://0.0.0.0:4001" 14 | }, 15 | { 16 | "name": "Compose", 17 | "command": "npm run compose" 18 | } 19 | ], 20 | "tasks": { 21 | "gateway": { 22 | "name": "Hive Gateway", 23 | "runAtStart": true, 24 | "command": "npm run gateway", 25 | "preview": { 26 | "port": 4000 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /examples/apq-subgraphs/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/apq-subgraphs/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/apq-subgraphs/example.tar.gz -------------------------------------------------------------------------------- /examples/apq-subgraphs/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | 3 | let fetchCnt = 0; 4 | export const gatewayConfig = defineConfig({ 5 | transportEntries: { 6 | greetings: { 7 | options: { 8 | apq: true, 9 | }, 10 | }, 11 | }, 12 | plugins: () => [ 13 | { 14 | onFetch({ options }) { 15 | fetchCnt++; 16 | process.stdout.write(`fetch ${fetchCnt} ${options.body}\n`); 17 | }, 18 | }, 19 | ], 20 | }); 21 | -------------------------------------------------------------------------------- /examples/apq-subgraphs/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | 6 | export const composeConfig = defineConfig({ 7 | subgraphs: [ 8 | { 9 | sourceHandler: loadGraphQLHTTPSubgraph('greetings', { 10 | endpoint: `http://localhost:${4001}/graphql`, 11 | }), 12 | }, 13 | ], 14 | }); 15 | -------------------------------------------------------------------------------- /examples/apq-subgraphs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/apq-subgraphs", 3 | "private": true, 4 | "devDependencies": { 5 | "tsx": "^4.19.3" 6 | }, 7 | "dependencies": { 8 | "@apollo/server": "^4.12.2", 9 | "@graphql-mesh/compose-cli": "^1.4.1", 10 | "graphql": "^16.9.0", 11 | "tslib": "^2.8.1", 12 | "@graphql-hive/gateway": "^1.15.0" 13 | }, 14 | "overrides": { 15 | "esbuild": "^0.25.4" 16 | }, 17 | "scripts": { 18 | "service:greetings": "tsx services/greetings.ts", 19 | "compose": "mesh-compose -o supergraph.graphql", 20 | "gateway": "hive-gateway supergraph" 21 | } 22 | } -------------------------------------------------------------------------------- /examples/apq-subgraphs/services/greetings.ts: -------------------------------------------------------------------------------- 1 | import { ApolloServer } from '@apollo/server'; 2 | import { startStandaloneServer } from '@apollo/server/standalone'; 3 | 4 | const apolloServer = new ApolloServer({ 5 | typeDefs: /* GraphQL */ ` 6 | type Query { 7 | hello: String 8 | } 9 | `, 10 | resolvers: { 11 | Query: { 12 | hello: () => 'world', 13 | }, 14 | }, 15 | }); 16 | 17 | startStandaloneServer(apolloServer, { 18 | listen: { port: 4001 }, 19 | }).catch((e) => { 20 | console.error(e); 21 | process.exit(1); 22 | }); 23 | -------------------------------------------------------------------------------- /examples/extra-fields/.codesandbox/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "setupTasks": [ 3 | { 4 | "name": "Install", 5 | "command": "npm i" 6 | }, 7 | { 8 | "name": "Start service foo", 9 | "command": "nohup npm run service:foo &> service-foo.out &" 10 | }, 11 | { 12 | "name": "Wait for service foo", 13 | "command": "curl --retry-connrefused --retry 10 --retry-delay 3 http://0.0.0.0:4001" 14 | }, 15 | { 16 | "name": "Start service bar", 17 | "command": "nohup npm run service:bar &> service-bar.out &" 18 | }, 19 | { 20 | "name": "Wait for service bar", 21 | "command": "curl --retry-connrefused --retry 10 --retry-delay 3 http://0.0.0.0:4002" 22 | }, 23 | { 24 | "name": "Compose", 25 | "command": "npm run compose" 26 | } 27 | ], 28 | "tasks": { 29 | "gateway": { 30 | "name": "Hive Gateway", 31 | "runAtStart": true, 32 | "command": "npm run gateway", 33 | "preview": { 34 | "port": 4000 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /examples/extra-fields/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/extra-fields/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/extra-fields/example.tar.gz -------------------------------------------------------------------------------- /examples/extra-fields/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | 6 | export const composeConfig = defineConfig({ 7 | subgraphs: [ 8 | { 9 | sourceHandler: loadGraphQLHTTPSubgraph('foo', { 10 | endpoint: `http://localhost:${4001}/graphql`, 11 | }), 12 | }, 13 | { 14 | sourceHandler: loadGraphQLHTTPSubgraph('bar', { 15 | endpoint: `http://localhost:${4002}/graphql`, 16 | }), 17 | }, 18 | ], 19 | additionalTypeDefs: /* GraphQL */ ` 20 | extend type Foo { 21 | bar: Bar 22 | @resolveTo( 23 | sourceName: "bar" 24 | sourceTypeName: "Query" 25 | sourceFieldName: "bar" 26 | ) 27 | } 28 | 29 | extend type Bar { 30 | foo: Foo 31 | @resolveTo( 32 | sourceName: "foo" 33 | sourceTypeName: "Query" 34 | sourceFieldName: "foo" 35 | ) 36 | } 37 | `, 38 | }); 39 | -------------------------------------------------------------------------------- /examples/extra-fields/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/extra-fields", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "graphql": "^16.9.0", 7 | "graphql-yoga": "^5.13.5", 8 | "tslib": "^2.8.1", 9 | "@graphql-hive/gateway": "^1.15.0" 10 | }, 11 | "devDependencies": { 12 | "tsx": "^4.19.3" 13 | }, 14 | "overrides": { 15 | "esbuild": "^0.25.4" 16 | }, 17 | "scripts": { 18 | "service:foo": "tsx services/foo.ts", 19 | "service:bar": "tsx services/bar.ts", 20 | "compose": "mesh-compose -o supergraph.graphql", 21 | "gateway": "hive-gateway supergraph" 22 | } 23 | } -------------------------------------------------------------------------------- /examples/extra-fields/services/bar.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { createSchema, createYoga } from 'graphql-yoga'; 3 | 4 | createServer( 5 | createYoga({ 6 | schema: createSchema({ 7 | typeDefs: /* GraphQL */ ` 8 | type Query { 9 | bar: Bar 10 | } 11 | 12 | type Bar { 13 | id: ID! 14 | } 15 | `, 16 | resolvers: { 17 | Query: { 18 | bar() { 19 | return { id: '1' }; 20 | }, 21 | }, 22 | }, 23 | }), 24 | }), 25 | ).listen(4002); 26 | -------------------------------------------------------------------------------- /examples/extra-fields/services/foo.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { createSchema, createYoga } from 'graphql-yoga'; 3 | 4 | createServer( 5 | createYoga({ 6 | schema: createSchema({ 7 | typeDefs: /* GraphQL */ ` 8 | type Query { 9 | foo: Foo 10 | } 11 | 12 | type Foo { 13 | id: ID! 14 | } 15 | `, 16 | resolvers: { 17 | Query: { 18 | foo() { 19 | return { id: '1' }; 20 | }, 21 | }, 22 | }, 23 | }), 24 | }), 25 | ).listen(4001); 26 | -------------------------------------------------------------------------------- /examples/federation-example/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/federation-example/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/federation-example/example.tar.gz -------------------------------------------------------------------------------- /examples/federation-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/federation-example", 3 | "private": true, 4 | "devDependencies": { 5 | "tsx": "^4.19.3", 6 | "@apollo/rover": "^0.32.1" 7 | }, 8 | "dependencies": { 9 | "@apollo/server": "^4.12.2", 10 | "@apollo/subgraph": "^2.11.0", 11 | "graphql": "^16.9.0", 12 | "@graphql-hive/gateway": "^1.15.0" 13 | }, 14 | "overrides": { 15 | "esbuild": "^0.25.4" 16 | }, 17 | "scripts": { 18 | "service:accounts": "tsx services/accounts/index.ts", 19 | "service:inventory": "tsx services/inventory/index.ts", 20 | "service:products": "tsx services/products/index.ts", 21 | "service:reviews": "tsx services/reviews/index.ts", 22 | "compose": "rover supergraph compose --elv2-license=accept --config supergraph.json --output supergraph.graphql", 23 | "gateway": "hive-gateway supergraph" 24 | } 25 | } -------------------------------------------------------------------------------- /examples/federation-example/services/accounts/index.ts: -------------------------------------------------------------------------------- 1 | import { startStandaloneServer } from '@apollo/server/standalone'; 2 | import { server } from './server'; 3 | 4 | startStandaloneServer(server, { 5 | listen: { port: 4001 }, 6 | }).catch((err) => { 7 | console.error(err); 8 | process.exit(1); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/federation-example/services/accounts/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | me: User 3 | user(id: ID!): User 4 | users: [User] 5 | } 6 | 7 | type User @key(fields: "id") { 8 | id: ID! 9 | name: String 10 | username: String 11 | } 12 | -------------------------------------------------------------------------------- /examples/federation-example/services/inventory/index.ts: -------------------------------------------------------------------------------- 1 | import { startStandaloneServer } from '@apollo/server/standalone'; 2 | import { server } from './server'; 3 | 4 | startStandaloneServer(server, { 5 | listen: { port: 4002 }, 6 | }).catch((err) => { 7 | console.error(err); 8 | process.exit(1); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/federation-example/services/inventory/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend type Product @key(fields: "upc") { 2 | upc: String! @external 3 | weight: Int @external 4 | price: Int @external 5 | inStock: Boolean 6 | shippingEstimate: Int @requires(fields: "price weight") 7 | } 8 | -------------------------------------------------------------------------------- /examples/federation-example/services/products/index.ts: -------------------------------------------------------------------------------- 1 | import { startStandaloneServer } from '@apollo/server/standalone'; 2 | import { server } from './server'; 3 | 4 | startStandaloneServer(server, { 5 | listen: { port: 4003 }, 6 | }).catch((err) => { 7 | console.error(err); 8 | process.exit(1); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/federation-example/services/products/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | topProducts(first: Int = 5): [Product] 3 | } 4 | 5 | type Product @key(fields: "upc") { 6 | upc: String! 7 | name: String 8 | price: Int 9 | weight: Int 10 | } 11 | -------------------------------------------------------------------------------- /examples/federation-example/services/reviews/index.ts: -------------------------------------------------------------------------------- 1 | import { startStandaloneServer } from '@apollo/server/standalone'; 2 | import { server } from './server'; 3 | 4 | startStandaloneServer(server, { 5 | listen: { port: 4004 }, 6 | }).catch((err) => { 7 | console.error(err); 8 | process.exit(1); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/federation-example/services/reviews/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | type Review @key(fields: "id") { 2 | id: ID! 3 | body: String 4 | author: User @provides(fields: "username") 5 | product: Product 6 | } 7 | 8 | extend type User @key(fields: "id") { 9 | id: ID! @external 10 | username: String @external 11 | reviews: [Review] 12 | numberOfReviews: Int 13 | } 14 | 15 | extend type Product @key(fields: "upc") { 16 | upc: String! @external 17 | reviews: [Review] 18 | } 19 | -------------------------------------------------------------------------------- /examples/federation-example/supergraph.json: -------------------------------------------------------------------------------- 1 | { 2 | "federation_version": "=2.9.0", 3 | "subgraphs": { 4 | "accounts": { 5 | "schema": { 6 | "subgraph_url": "http://0.0.0.0:4001/graphql" 7 | } 8 | }, 9 | "inventory": { 10 | "schema": { 11 | "subgraph_url": "http://0.0.0.0:4002/graphql" 12 | } 13 | }, 14 | "products": { 15 | "schema": { 16 | "subgraph_url": "http://0.0.0.0:4003/graphql" 17 | } 18 | }, 19 | "reviews": { 20 | "schema": { 21 | "subgraph_url": "http://0.0.0.0:4004/graphql" 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /examples/federation-mixed/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/federation-mixed/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/federation-mixed/example.tar.gz -------------------------------------------------------------------------------- /examples/federation-mixed/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/federation-mixed", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "graphql": "^16.9.0", 8 | "tslib": "^2.8.1", 9 | "@apollo/server": "^4.12.2", 10 | "@apollo/subgraph": "^2.11.0", 11 | "fets": "^0.8.4", 12 | "@graphql-hive/gateway": "^1.15.0" 13 | }, 14 | "devDependencies": { 15 | "tsx": "^4.19.3", 16 | "@apollo/rover": "^0.32.1" 17 | }, 18 | "overrides": { 19 | "esbuild": "^0.25.4" 20 | }, 21 | "scripts": { 22 | "service:accounts": "tsx services/accounts/index.ts", 23 | "service:inventory": "tsx services/inventory/index.ts", 24 | "service:products": "tsx services/products/index.ts", 25 | "service:reviews": "tsx services/reviews/index.ts", 26 | "compose": "mesh-compose -o supergraph.graphql", 27 | "gateway": "hive-gateway supergraph" 28 | } 29 | } -------------------------------------------------------------------------------- /examples/federation-mixed/services/accounts/index.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { server } from './server'; 3 | 4 | const httpServer = createServer(server).listen(4001); 5 | 6 | httpServer.once('error', (err) => { 7 | console.error(err); 8 | process.exit(1); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/federation-mixed/services/inventory/index.ts: -------------------------------------------------------------------------------- 1 | import { startStandaloneServer } from '@apollo/server/standalone'; 2 | import { server } from './server'; 3 | 4 | startStandaloneServer(server, { 5 | listen: { port: 4002 }, 6 | }).catch((err) => { 7 | console.error(err); 8 | process.exit(1); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/federation-mixed/services/inventory/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend type Product @key(fields: "upc") { 2 | upc: String! @external 3 | weight: Int @external 4 | price: Int @external 5 | inStock: Boolean 6 | shippingEstimate: Int @requires(fields: "price weight") 7 | } 8 | -------------------------------------------------------------------------------- /examples/federation-mixed/services/products/index.ts: -------------------------------------------------------------------------------- 1 | import { startStandaloneServer } from '@apollo/server/standalone'; 2 | import { server } from './server'; 3 | 4 | startStandaloneServer(server, { 5 | listen: { port: 4003 }, 6 | }).catch((err) => { 7 | console.error(err); 8 | process.exit(1); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/federation-mixed/services/products/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | topProducts(first: Int = 5): [Product] 3 | } 4 | 5 | type Product @key(fields: "upc") { 6 | upc: String! 7 | name: String 8 | price: Int 9 | weight: Int 10 | } 11 | -------------------------------------------------------------------------------- /examples/federation-mixed/services/reviews/index.ts: -------------------------------------------------------------------------------- 1 | import { startStandaloneServer } from '@apollo/server/standalone'; 2 | import { server } from './server'; 3 | 4 | startStandaloneServer(server, { 5 | listen: { port: 4004 }, 6 | }).catch((err) => { 7 | console.error(err); 8 | process.exit(1); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/federation-mixed/services/reviews/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | type Review @key(fields: "id") { 2 | id: ID! 3 | body: String 4 | author: User @provides(fields: "username") 5 | product: Product 6 | } 7 | 8 | extend type User @key(fields: "id") { 9 | id: ID! @external 10 | username: String @external 11 | reviews: [Review] 12 | numberOfReviews: Int 13 | } 14 | 15 | extend type Product @key(fields: "upc") { 16 | upc: String! @external 17 | reviews: [Review] 18 | } 19 | -------------------------------------------------------------------------------- /examples/federation-subscriptions-passthrough/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/federation-subscriptions-passthrough/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/federation-subscriptions-passthrough/example.tar.gz -------------------------------------------------------------------------------- /examples/federation-subscriptions-passthrough/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | type HTTPCallbackTransportOptions, 4 | type WSTransportOptions, 5 | } from '@graphql-hive/gateway'; 6 | 7 | export const gatewayConfig = defineConfig({ 8 | webhooks: true, 9 | transportEntries: { 10 | products: { 11 | options: { 12 | subscriptions: { 13 | kind: 'ws', 14 | location: '/subscriptions', 15 | options: { 16 | connectionParams: { 17 | token: '{context.headers.authorization}', 18 | }, 19 | } satisfies WSTransportOptions, 20 | }, 21 | }, 22 | }, 23 | reviews: { 24 | options: { 25 | subscriptions: { 26 | kind: 'http-callback', 27 | options: { 28 | public_url: process.env['PUBLIC_URL'], 29 | } satisfies HTTPCallbackTransportOptions, 30 | }, 31 | }, 32 | }, 33 | }, 34 | }); 35 | -------------------------------------------------------------------------------- /examples/federation-subscriptions-passthrough/services/products/index.ts: -------------------------------------------------------------------------------- 1 | import { start } from './server'; 2 | 3 | start(4001).catch((err) => { 4 | console.error(err); 5 | process.exit(1); 6 | }); 7 | -------------------------------------------------------------------------------- /examples/federation-subscriptions-passthrough/services/products/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | topProducts(first: Int = 3): [Product] 3 | } 4 | 5 | type Subscription { 6 | productPriceChanged: Product! 7 | newProduct: Product! 8 | } 9 | 10 | type Product @key(fields: "id") { 11 | id: ID! 12 | name: String! 13 | price: Int! 14 | } 15 | -------------------------------------------------------------------------------- /examples/federation-subscriptions-passthrough/services/reviews/index.ts: -------------------------------------------------------------------------------- 1 | import { start } from './server'; 2 | 3 | start(4002).catch((err) => { 4 | console.error(err); 5 | process.exit(1); 6 | }); 7 | -------------------------------------------------------------------------------- /examples/federation-subscriptions-passthrough/services/reviews/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend type Product @key(fields: "id") { 2 | id: ID! @external 3 | reviews: [Review!]! 4 | } 5 | 6 | type Review { 7 | score: Int! 8 | } 9 | 10 | type Subscription { 11 | countdown(from: Int!): Int 12 | newReview: Review! 13 | } 14 | -------------------------------------------------------------------------------- /examples/federation-subscriptions-passthrough/supergraph.json: -------------------------------------------------------------------------------- 1 | { 2 | "federation_version": "=2.9.0", 3 | "subgraphs": { 4 | "products": { 5 | "schema": { 6 | "subgraph_url": "http://0.0.0.0:4001/graphql" 7 | } 8 | }, 9 | "reviews": { 10 | "schema": { 11 | "subgraph_url": "http://0.0.0.0:4002/graphql" 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /examples/file-upload/.codesandbox/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "setupTasks": [ 3 | { 4 | "name": "Install", 5 | "command": "npm i" 6 | }, 7 | { 8 | "name": "Start service bucket", 9 | "command": "nohup npm run service:bucket &> service-bucket.out &" 10 | }, 11 | { 12 | "name": "Wait for service bucket", 13 | "command": "curl --retry-connrefused --retry 10 --retry-delay 3 http://0.0.0.0:4001" 14 | }, 15 | { 16 | "name": "Compose", 17 | "command": "npm run compose" 18 | } 19 | ], 20 | "tasks": { 21 | "gateway": { 22 | "name": "Hive Gateway", 23 | "runAtStart": true, 24 | "command": "npm run gateway", 25 | "preview": { 26 | "port": 4000 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /examples/file-upload/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/file-upload/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/file-upload/example.tar.gz -------------------------------------------------------------------------------- /examples/file-upload/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | 6 | export const composeConfig = defineConfig({ 7 | subgraphs: [ 8 | { 9 | sourceHandler: loadGraphQLHTTPSubgraph('bucket', { 10 | endpoint: `http://localhost:${4001}/graphql`, 11 | }), 12 | }, 13 | ], 14 | }); 15 | -------------------------------------------------------------------------------- /examples/file-upload/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/file-upload", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "graphql": "^16.9.0", 7 | "tslib": "^2.8.1", 8 | "@graphql-hive/gateway": "^1.15.0" 9 | }, 10 | "devDependencies": { 11 | "tsx": "^4.19.3" 12 | }, 13 | "overrides": { 14 | "esbuild": "^0.25.4" 15 | }, 16 | "scripts": { 17 | "service:bucket": "tsx services/bucket.ts", 18 | "compose": "mesh-compose -o supergraph.graphql", 19 | "gateway": "hive-gateway supergraph" 20 | } 21 | } -------------------------------------------------------------------------------- /examples/file-upload/services/bucket.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { createSchema, createYoga } from 'graphql-yoga'; 3 | 4 | createServer( 5 | createYoga({ 6 | maskedErrors: false, 7 | schema: createSchema({ 8 | typeDefs: /* GraphQL */ ` 9 | scalar Upload # intentionally not "File" to test scalar name independence 10 | type Query { 11 | hello: String! 12 | } 13 | type Mutation { 14 | readFile(file: Upload!): String 15 | } 16 | `, 17 | resolvers: { 18 | Query: { 19 | hello: () => 'world', 20 | }, 21 | Mutation: { 22 | readFile(_parent, { file }: { file: File }) { 23 | return file.text(); 24 | }, 25 | }, 26 | }, 27 | }), 28 | }), 29 | ).listen(4001); 30 | -------------------------------------------------------------------------------- /examples/hmac-auth-https/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/hmac-auth-https/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/hmac-auth-https/example.tar.gz -------------------------------------------------------------------------------- /examples/hmac-auth-https/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createInlineSigningKeyProvider, 3 | defineConfig, 4 | } from '@graphql-hive/gateway'; 5 | 6 | export const gatewayConfig = defineConfig({ 7 | hmacSignature: { 8 | secret: 'HMAC_SIGNING_SECRET', 9 | }, 10 | jwt: { 11 | forward: { 12 | payload: true, 13 | token: false, 14 | }, 15 | signingKeyProviders: [createInlineSigningKeyProvider('JWT_SIGNING_SECRET')], 16 | reject: { 17 | missingToken: false, 18 | invalidToken: false, 19 | }, 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /examples/hmac-auth-https/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | 6 | export const composeConfig = defineConfig({ 7 | subgraphs: [ 8 | { 9 | sourceHandler: loadGraphQLHTTPSubgraph('users', { 10 | endpoint: `https://localhost:${4001}/graphql`, 11 | source: './services/users/typeDefs.graphql', 12 | }), 13 | }, 14 | { 15 | sourceHandler: loadGraphQLHTTPSubgraph('comments', { 16 | endpoint: `http://localhost:${4002}/graphql`, 17 | source: './services/comments/typeDefs.graphql', 18 | }), 19 | }, 20 | ], 21 | }); 22 | -------------------------------------------------------------------------------- /examples/hmac-auth-https/services/comments/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend schema 2 | @link( 3 | url: "https://specs.apollo.dev/federation/v2.5" 4 | import: ["@key", "@requiresScopes"] 5 | ) 6 | 7 | type Comment @key(fields: "id") { 8 | id: ID! 9 | text: String! 10 | author: User! 11 | } 12 | 13 | type User @key(fields: "id") { 14 | id: ID! 15 | comments: [Comment!]! @requiresScopes(scopes: [["ReadComments"]]) 16 | } 17 | 18 | type Query { 19 | comments: [Comment] 20 | } 21 | -------------------------------------------------------------------------------- /examples/hmac-auth-https/services/users/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend schema 2 | @link( 3 | url: "https://specs.apollo.dev/federation/v2.5" 4 | import: ["@key", "@requiresScopes", "@authenticated"] 5 | ) 6 | 7 | type User @key(fields: "id") { 8 | id: ID! 9 | name: String! @requiresScopes(scopes: [["ReadUsersName"]]) 10 | } 11 | 12 | type Query { 13 | me: User @authenticated 14 | users: [User] 15 | user(id: ID!): User 16 | } 17 | -------------------------------------------------------------------------------- /examples/interface-additional-resolvers/.codesandbox/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "setupTasks": [ 3 | { 4 | "name": "Install", 5 | "command": "npm i" 6 | }, 7 | { 8 | "name": "Start service Test", 9 | "command": "nohup npm run service:Test &> service-Test.out &" 10 | }, 11 | { 12 | "name": "Wait for service Test", 13 | "command": "curl --retry-connrefused --retry 10 --retry-delay 3 http://0.0.0.0:4001" 14 | }, 15 | { 16 | "name": "Compose", 17 | "command": "npm run compose" 18 | } 19 | ], 20 | "tasks": { 21 | "gateway": { 22 | "name": "Hive Gateway", 23 | "runAtStart": true, 24 | "command": "npm run gateway", 25 | "preview": { 26 | "port": 4000 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /examples/interface-additional-resolvers/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/interface-additional-resolvers/additionalTypeDefs/Node.graphql: -------------------------------------------------------------------------------- 1 | extend interface Node { 2 | self: Node! 3 | @resolveTo( 4 | sourceName: "Test" 5 | sourceTypeName: "Query" 6 | sourceFieldName: "node" 7 | sourceArgs: { id: "{root.id}" } 8 | requiredSelectionSet: "{ id }" 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /examples/interface-additional-resolvers/additionalTypeDefs/User.ts: -------------------------------------------------------------------------------- 1 | export const extraDefs = /* GraphQL */ ` 2 | extend type User implements Node { 3 | self: Node! 4 | } 5 | `; 6 | -------------------------------------------------------------------------------- /examples/interface-additional-resolvers/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/interface-additional-resolvers/example.tar.gz -------------------------------------------------------------------------------- /examples/interface-additional-resolvers/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | 3 | export const gatewayConfig = defineConfig({ 4 | additionalTypeDefs: './additionalTypeDefs/*.graphql', 5 | }); 6 | -------------------------------------------------------------------------------- /examples/interface-additional-resolvers/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | 6 | export const composeConfig = defineConfig({ 7 | subgraphs: [ 8 | { 9 | sourceHandler: loadGraphQLHTTPSubgraph('Test', { 10 | endpoint: `http://localhost:${4001}/graphql`, 11 | }), 12 | }, 13 | ], 14 | additionalTypeDefs: './additionalTypeDefs/*', 15 | }); 16 | -------------------------------------------------------------------------------- /examples/interface-additional-resolvers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/interface-additional-resolvers", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "graphql": "^16.9.0", 7 | "graphql-yoga": "^5.13.5", 8 | "tslib": "^2.8.1", 9 | "@graphql-hive/gateway": "^1.15.0" 10 | }, 11 | "devDependencies": { 12 | "tsx": "^4.19.3" 13 | }, 14 | "overrides": { 15 | "esbuild": "^0.25.4" 16 | }, 17 | "scripts": { 18 | "service:Test": "tsx services/Test.ts", 19 | "compose": "mesh-compose -o supergraph.graphql", 20 | "gateway": "hive-gateway supergraph" 21 | } 22 | } -------------------------------------------------------------------------------- /examples/interface-additional-resolvers/services/Test.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'node:http'; 2 | import { createSchema, createYoga } from 'graphql-yoga'; 3 | 4 | export const yoga = createYoga({ 5 | schema: createSchema({ 6 | typeDefs: /* GraphQL */ ` 7 | interface Node { 8 | id: ID! 9 | } 10 | 11 | type User implements Node { 12 | id: ID! 13 | name: String! 14 | } 15 | 16 | type Query { 17 | node(id: ID!): Node 18 | user(id: ID!): User 19 | } 20 | `, 21 | resolvers: { 22 | Node: { 23 | __resolveType: (obj: { __typename: string }) => obj.__typename, 24 | }, 25 | Query: { 26 | node: () => ({ __typename: 'User', id: '1', name: 'Alice' }), 27 | }, 28 | }, 29 | }), 30 | maskedErrors: false, 31 | }); 32 | 33 | createServer(yoga).listen(4001, () => { 34 | console.log( 35 | `🚀 Server ready at http://localhost:${4001}/graphql`, 36 | ); 37 | }); 38 | -------------------------------------------------------------------------------- /examples/json-schema-subscriptions/.codesandbox/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "setupTasks": [ 3 | { 4 | "name": "Install", 5 | "command": "npm i" 6 | }, 7 | { 8 | "name": "Start service api", 9 | "command": "nohup npm run service:api &> service-api.out &" 10 | }, 11 | { 12 | "name": "Wait for service api", 13 | "command": "curl --retry-connrefused --retry 10 --retry-delay 3 http://0.0.0.0:4001" 14 | }, 15 | { 16 | "name": "Compose", 17 | "command": "npm run compose" 18 | } 19 | ], 20 | "tasks": { 21 | "gateway": { 22 | "name": "Hive Gateway", 23 | "runAtStart": true, 24 | "command": "npm run gateway", 25 | "preview": { 26 | "port": 4000 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /examples/json-schema-subscriptions/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/json-schema-subscriptions/addTodo.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TodoName", 3 | "content": "TodoContent" 4 | } 5 | -------------------------------------------------------------------------------- /examples/json-schema-subscriptions/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/json-schema-subscriptions/example.tar.gz -------------------------------------------------------------------------------- /examples/json-schema-subscriptions/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | import useMeshLiveQuery from '@graphql-mesh/plugin-live-query'; 3 | 4 | export const gatewayConfig = defineConfig({ 5 | webhooks: true, 6 | plugins: (ctx) => [ 7 | useMeshLiveQuery({ 8 | ...ctx, 9 | invalidations: [ 10 | { 11 | field: 'Mutation.addTodo', 12 | invalidate: ['Query.todos'], 13 | }, 14 | ], 15 | }), 16 | ], 17 | }); 18 | -------------------------------------------------------------------------------- /examples/json-schema-subscriptions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/json-schema-subscriptions", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@graphql-mesh/cross-helpers": "^0.4.10", 7 | "@graphql-mesh/plugin-live-query": "^0.104.0", 8 | "@omnigraph/json-schema": "^0.109.5", 9 | "fets": "^0.8.4", 10 | "graphql": "^16.9.0", 11 | "graphql-sse": "^2.5.3", 12 | "tslib": "^2.8.1", 13 | "@graphql-hive/gateway": "^1.15.0" 14 | }, 15 | "devDependencies": { 16 | "tsx": "^4.19.3" 17 | }, 18 | "overrides": { 19 | "esbuild": "^0.25.4" 20 | }, 21 | "scripts": { 22 | "service:api": "tsx services/api.ts", 23 | "compose": "mesh-compose -o supergraph.graphql", 24 | "gateway": "hive-gateway supergraph" 25 | } 26 | } -------------------------------------------------------------------------------- /examples/json-schema-subscriptions/todo.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 0, 3 | "name": "TodoName", 4 | "content": "TodoContent" 5 | } 6 | -------------------------------------------------------------------------------- /examples/json-schema-subscriptions/todos.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 0, 4 | "name": "TodoName", 5 | "content": "TodoContent" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /examples/openapi-additional-resolvers/.codesandbox/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "setupTasks": [ 3 | { 4 | "name": "Install", 5 | "command": "npm i" 6 | }, 7 | { 8 | "name": "Compose", 9 | "command": "npm run compose" 10 | } 11 | ], 12 | "tasks": { 13 | "gateway": { 14 | "name": "Hive Gateway", 15 | "runAtStart": true, 16 | "command": "npm run gateway", 17 | "preview": { 18 | "port": 4000 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /examples/openapi-additional-resolvers/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/openapi-additional-resolvers/additionalTypeDefs/apple.graphql: -------------------------------------------------------------------------------- 1 | extend type pageview_project { 2 | apple: String! 3 | } 4 | -------------------------------------------------------------------------------- /examples/openapi-additional-resolvers/additionalTypeDefs/banana.graphql: -------------------------------------------------------------------------------- 1 | extend type pageview_project { 2 | banana: String 3 | } 4 | -------------------------------------------------------------------------------- /examples/openapi-additional-resolvers/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/openapi-additional-resolvers/example.tar.gz -------------------------------------------------------------------------------- /examples/openapi-additional-resolvers/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | 3 | export const gatewayConfig = defineConfig({ 4 | additionalResolvers: { 5 | pageview_project: { 6 | banana() { 7 | return '🍌'; 8 | }, 9 | apple() { 10 | return '🍎'; 11 | }, 12 | }, 13 | }, 14 | }); 15 | -------------------------------------------------------------------------------- /examples/openapi-additional-resolvers/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-mesh/compose-cli'; 2 | import { loadOpenAPISubgraph } from '@omnigraph/openapi'; 3 | 4 | export const composeConfig = defineConfig({ 5 | subgraphs: [ 6 | { 7 | sourceHandler: loadOpenAPISubgraph('Wiki', { 8 | source: 9 | 'https://api.apis.guru/v2/specs/wikimedia.org/1.0.0/swagger.yaml', 10 | endpoint: 'https://wikimedia.org/api/rest_v1', 11 | }), 12 | }, 13 | ], 14 | additionalTypeDefs: './additionalTypeDefs/*.graphql', 15 | }); 16 | -------------------------------------------------------------------------------- /examples/openapi-additional-resolvers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/openapi-additional-resolvers", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "graphql": "^16.9.0", 8 | "moment": "^2.30.1", 9 | "tslib": "^2.8.1", 10 | "@graphql-hive/gateway": "^1.15.0" 11 | }, 12 | "scripts": { 13 | "compose": "mesh-compose -o supergraph.graphql", 14 | "gateway": "hive-gateway supergraph" 15 | } 16 | } -------------------------------------------------------------------------------- /examples/openapi-arg-rename/.codesandbox/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "setupTasks": [ 3 | { 4 | "name": "Install", 5 | "command": "npm i" 6 | }, 7 | { 8 | "name": "Start service Wiki", 9 | "command": "nohup npm run service:Wiki &> service-Wiki.out &" 10 | }, 11 | { 12 | "name": "Wait for service Wiki", 13 | "command": "curl --retry-connrefused --retry 10 --retry-delay 3 http://0.0.0.0:4001" 14 | }, 15 | { 16 | "name": "Compose", 17 | "command": "npm run compose" 18 | } 19 | ], 20 | "tasks": { 21 | "gateway": { 22 | "name": "Hive Gateway", 23 | "runAtStart": true, 24 | "command": "npm run gateway", 25 | "preview": { 26 | "port": 4000 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /examples/openapi-arg-rename/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/openapi-arg-rename/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/openapi-arg-rename/example.tar.gz -------------------------------------------------------------------------------- /examples/openapi-arg-rename/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | camelCase, 3 | createNamingConventionTransform, 4 | createRenameTransform, 5 | defineConfig, 6 | } from '@graphql-mesh/compose-cli'; 7 | import { loadOpenAPISubgraph } from '@omnigraph/openapi'; 8 | 9 | export const composeConfig = defineConfig({ 10 | subgraphs: [ 11 | { 12 | sourceHandler: loadOpenAPISubgraph('Wiki', { 13 | source: './openapi.json', 14 | endpoint: `http://localhost:${4001}`, 15 | }), 16 | transforms: [ 17 | createNamingConventionTransform({ 18 | fieldNames: camelCase, 19 | }), 20 | createRenameTransform({ 21 | argRenamer: ({ argName, fieldName }) => { 22 | if (fieldName === 'postBad' && argName === 'input') { 23 | return 'requestBody'; 24 | } 25 | 26 | return argName; 27 | }, 28 | }), 29 | ], 30 | }, 31 | ], 32 | }); 33 | -------------------------------------------------------------------------------- /examples/openapi-arg-rename/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/openapi-arg-rename", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "graphql": "16.11.0", 8 | "moment": "2.30.1", 9 | "tslib": "^2.8.1", 10 | "@graphql-hive/gateway": "^1.15.0" 11 | }, 12 | "devDependencies": { 13 | "tsx": "^4.19.3" 14 | }, 15 | "overrides": { 16 | "esbuild": "^0.25.4" 17 | }, 18 | "scripts": { 19 | "service:Wiki": "tsx services/Wiki.ts", 20 | "compose": "mesh-compose -o supergraph.graphql", 21 | "gateway": "hive-gateway supergraph" 22 | } 23 | } -------------------------------------------------------------------------------- /examples/openapi-arg-rename/services/Wiki.ts: -------------------------------------------------------------------------------- 1 | import http from 'node:http'; 2 | 3 | const server = http.createServer((req, res) => { 4 | if (req.url?.endsWith('good')) { 5 | res.setHeader('content-type', 'application/json'); 6 | res.end(JSON.stringify({ apple: 'good' })); 7 | return; 8 | } 9 | if (req.url?.endsWith('bad')) { 10 | res.setHeader('content-type', 'application/json'); 11 | res.end(JSON.stringify({ apple: 'bad' })); 12 | return; 13 | } 14 | res.writeHead(404); 15 | res.end(); 16 | return; 17 | }); 18 | 19 | server.listen(4001); 20 | -------------------------------------------------------------------------------- /examples/openapi-javascript-wiki/.codesandbox/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "setupTasks": [ 3 | { 4 | "name": "Install", 5 | "command": "npm i" 6 | }, 7 | { 8 | "name": "Compose", 9 | "command": "npm run compose" 10 | } 11 | ], 12 | "tasks": { 13 | "gateway": { 14 | "name": "Hive Gateway", 15 | "runAtStart": true, 16 | "command": "npm run gateway", 17 | "preview": { 18 | "port": 4000 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /examples/openapi-javascript-wiki/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/openapi-javascript-wiki/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/openapi-javascript-wiki/example.tar.gz -------------------------------------------------------------------------------- /examples/openapi-javascript-wiki/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-mesh/compose-cli'; 2 | import { loadOpenAPISubgraph } from '@omnigraph/openapi'; 3 | 4 | export const composeConfig = defineConfig({ 5 | subgraphs: [ 6 | { 7 | sourceHandler: loadOpenAPISubgraph('Wiki', { 8 | source: 9 | 'https://api.apis.guru/v2/specs/wikimedia.org/1.0.0/swagger.yaml', 10 | endpoint: 'https://wikimedia.org/api/rest_v1', 11 | ignoreErrorResponses: true, 12 | }), 13 | }, 14 | ], 15 | additionalTypeDefs: /* GraphQL */ ` 16 | extend type Query { 17 | viewsInPastMonth(project: String!): Int! 18 | } 19 | `, 20 | }); 21 | -------------------------------------------------------------------------------- /examples/openapi-javascript-wiki/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/openapi-javascript-wiki", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "graphql": "^16.9.0", 8 | "moment": "^2.30.1", 9 | "tslib": "^2.8.1", 10 | "@graphql-hive/gateway": "^1.15.0" 11 | }, 12 | "scripts": { 13 | "compose": "mesh-compose -o supergraph.graphql", 14 | "gateway": "hive-gateway supergraph" 15 | } 16 | } -------------------------------------------------------------------------------- /examples/openapi-subscriptions/.codesandbox/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "setupTasks": [ 3 | { 4 | "name": "Install", 5 | "command": "npm i" 6 | }, 7 | { 8 | "name": "Start service api", 9 | "command": "nohup npm run service:api &> service-api.out &" 10 | }, 11 | { 12 | "name": "Wait for service api", 13 | "command": "curl --retry-connrefused --retry 10 --retry-delay 3 http://0.0.0.0:4001" 14 | }, 15 | { 16 | "name": "Compose", 17 | "command": "npm run compose" 18 | } 19 | ], 20 | "tasks": { 21 | "gateway": { 22 | "name": "Hive Gateway", 23 | "runAtStart": true, 24 | "command": "npm run gateway", 25 | "preview": { 26 | "port": 4000 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /examples/openapi-subscriptions/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/openapi-subscriptions/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/openapi-subscriptions/example.tar.gz -------------------------------------------------------------------------------- /examples/openapi-subscriptions/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-hive/gateway'; 2 | 3 | export const gatewayConfig = defineConfig({ 4 | webhooks: true, 5 | }); 6 | -------------------------------------------------------------------------------- /examples/openapi-subscriptions/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-mesh/compose-cli'; 2 | import { loadOpenAPISubgraph } from '@omnigraph/openapi'; 3 | 4 | export const composeConfig = defineConfig({ 5 | subgraphs: [ 6 | { 7 | sourceHandler: loadOpenAPISubgraph('OpenAPICallbackExample', { 8 | source: './services/api/openapi.yml', 9 | endpoint: `http://localhost:${4001}`, 10 | }), 11 | }, 12 | ], 13 | }); 14 | -------------------------------------------------------------------------------- /examples/openapi-subscriptions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/openapi-subscriptions", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "fets": "^0.8.4", 8 | "graphql": "^16.9.0", 9 | "graphql-sse": "^2.5.3", 10 | "tslib": "^2.8.1", 11 | "url-join": "^5.0.0", 12 | "@graphql-hive/gateway": "^1.15.0" 13 | }, 14 | "devDependencies": { 15 | "tsx": "^4.19.3" 16 | }, 17 | "overrides": { 18 | "esbuild": "^0.25.4" 19 | }, 20 | "scripts": { 21 | "service:api": "tsx services/api/index.ts", 22 | "compose": "mesh-compose -o supergraph.graphql", 23 | "gateway": "hive-gateway supergraph" 24 | } 25 | } -------------------------------------------------------------------------------- /examples/operation-field-permissions/.codesandbox/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "setupTasks": [ 3 | { 4 | "name": "Install", 5 | "command": "npm i" 6 | }, 7 | { 8 | "name": "Start service users", 9 | "command": "nohup npm run service:users &> service-users.out &" 10 | }, 11 | { 12 | "name": "Wait for service users", 13 | "command": "curl --retry-connrefused --retry 10 --retry-delay 3 http://0.0.0.0:4001" 14 | }, 15 | { 16 | "name": "Compose", 17 | "command": "npm run compose" 18 | } 19 | ], 20 | "tasks": { 21 | "gateway": { 22 | "name": "Hive Gateway", 23 | "runAtStart": true, 24 | "command": "npm run gateway", 25 | "preview": { 26 | "port": 4000 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /examples/operation-field-permissions/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/operation-field-permissions/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/operation-field-permissions/example.tar.gz -------------------------------------------------------------------------------- /examples/operation-field-permissions/gateway.config.ts: -------------------------------------------------------------------------------- 1 | import { useOperationFieldPermissions } from '@envelop/operation-field-permissions'; 2 | import { defineConfig, GatewayContext } from '@graphql-hive/gateway'; 3 | 4 | export const gatewayConfig = defineConfig({ 5 | plugins: () => [ 6 | useOperationFieldPermissions({ 7 | getPermissions(ctx: GatewayContext) { 8 | const auth = ctx.request.headers.get('authorization'); 9 | if ( 10 | auth === 11 | 'Bearer TOKEN' /** NOTE: proper token validity check goes here */ 12 | ) { 13 | // allow all fields 14 | return new Set(['*']); 15 | } 16 | // allow only introspection 17 | return new Set(['Query.registrationOpen']); 18 | }, 19 | }) as any, // TODO: fix generic in envelop 20 | ], 21 | }); 22 | -------------------------------------------------------------------------------- /examples/operation-field-permissions/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | loadGraphQLHTTPSubgraph, 4 | } from '@graphql-mesh/compose-cli'; 5 | 6 | export const composeConfig = defineConfig({ 7 | subgraphs: [ 8 | { 9 | sourceHandler: loadGraphQLHTTPSubgraph('users', { 10 | endpoint: `http://localhost:${4001}/graphql`, 11 | }), 12 | }, 13 | ], 14 | }); 15 | -------------------------------------------------------------------------------- /examples/operation-field-permissions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/operation-field-permissions", 3 | "private": true, 4 | "dependencies": { 5 | "@envelop/core": "^5.2.3", 6 | "@envelop/operation-field-permissions": "^7.0.0", 7 | "@graphql-mesh/compose-cli": "^1.4.1", 8 | "graphql": "^16.10.0", 9 | "@graphql-hive/gateway": "^1.15.0" 10 | }, 11 | "devDependencies": { 12 | "tsx": "^4.19.3" 13 | }, 14 | "overrides": { 15 | "esbuild": "^0.25.4" 16 | }, 17 | "scripts": { 18 | "service:users": "tsx services/users.ts", 19 | "compose": "mesh-compose -o supergraph.graphql", 20 | "gateway": "hive-gateway supergraph" 21 | } 22 | } -------------------------------------------------------------------------------- /examples/operation-field-permissions/services/users.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from 'http'; 2 | import { createSchema, createYoga } from 'graphql-yoga'; 3 | 4 | createServer( 5 | createYoga({ 6 | maskedErrors: false, 7 | schema: createSchema({ 8 | typeDefs: /* GraphQL */ ` 9 | type Query { 10 | registrationOpen: Boolean! 11 | me: User! 12 | } 13 | type User { 14 | name: String! 15 | } 16 | `, 17 | resolvers: { 18 | Query: { 19 | registrationOpen: () => false, 20 | me: () => ({ name: 'John' }), 21 | }, 22 | }, 23 | }), 24 | }), 25 | ).listen(4001); 26 | -------------------------------------------------------------------------------- /examples/programmatic-batching/.codesandbox/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "setupTasks": [ 3 | { 4 | "name": "Install", 5 | "command": "npm i" 6 | }, 7 | { 8 | "name": "Start service api", 9 | "command": "nohup npm run service:api &> service-api.out &" 10 | }, 11 | { 12 | "name": "Wait for service api", 13 | "command": "curl --retry-connrefused --retry 10 --retry-delay 3 http://0.0.0.0:4001" 14 | }, 15 | { 16 | "name": "Compose", 17 | "command": "npm run compose" 18 | } 19 | ], 20 | "tasks": { 21 | "gateway": { 22 | "name": "Hive Gateway", 23 | "runAtStart": true, 24 | "command": "npm run gateway", 25 | "preview": { 26 | "port": 4000 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /examples/programmatic-batching/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/programmatic-batching/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/programmatic-batching/example.tar.gz -------------------------------------------------------------------------------- /examples/programmatic-batching/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@graphql-mesh/compose-cli'; 2 | import { loadOpenAPISubgraph } from '@omnigraph/openapi'; 3 | 4 | export const composeConfig = defineConfig({ 5 | subgraphs: [ 6 | { 7 | sourceHandler: loadOpenAPISubgraph('API', { 8 | source: `http://localhost:${4001}/openapi.json`, 9 | endpoint: `http://localhost:${4001}`, 10 | ignoreErrorResponses: true, 11 | }), 12 | }, 13 | ], 14 | additionalTypeDefs: /* GraphQL */ ` 15 | extend type Query { 16 | user(id: Float!): User 17 | } 18 | `, 19 | }); 20 | -------------------------------------------------------------------------------- /examples/programmatic-batching/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/programmatic-batching", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "@omnigraph/openapi": "^0.109.10", 7 | "fets": "^0.8.4", 8 | "graphql": "16.11.0", 9 | "tslib": "^2.8.1", 10 | "@graphql-hive/gateway": "^1.15.0" 11 | }, 12 | "devDependencies": { 13 | "tsx": "^4.19.3" 14 | }, 15 | "overrides": { 16 | "esbuild": "^0.25.4" 17 | }, 18 | "scripts": { 19 | "service:api": "tsx services/api.ts", 20 | "compose": "mesh-compose -o supergraph.graphql", 21 | "gateway": "hive-gateway supergraph" 22 | } 23 | } -------------------------------------------------------------------------------- /examples/subscriptions-with-transforms/.codesandbox/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "setupTasks": [ 3 | { 4 | "name": "Install", 5 | "command": "npm i" 6 | }, 7 | { 8 | "name": "Start service my-subgraph", 9 | "command": "nohup npm run service:my-subgraph &> service-my-subgraph.out &" 10 | }, 11 | { 12 | "name": "Wait for service my-subgraph", 13 | "command": "curl --retry-connrefused --retry 10 --retry-delay 3 http://0.0.0.0:4001" 14 | }, 15 | { 16 | "name": "Compose", 17 | "command": "npm run compose" 18 | } 19 | ], 20 | "tasks": { 21 | "gateway": { 22 | "name": "Hive Gateway", 23 | "runAtStart": true, 24 | "command": "npm run gateway", 25 | "preview": { 26 | "port": 4000 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /examples/subscriptions-with-transforms/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/subscriptions-with-transforms/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/subscriptions-with-transforms/example.tar.gz -------------------------------------------------------------------------------- /examples/subscriptions-with-transforms/mesh.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createPrefixTransform, 3 | defineConfig, 4 | loadGraphQLHTTPSubgraph, 5 | } from '@graphql-mesh/compose-cli'; 6 | 7 | export const composeConfig = defineConfig({ 8 | subgraphs: [ 9 | { 10 | sourceHandler: loadGraphQLHTTPSubgraph('my-subgraph', { 11 | endpoint: `http://localhost:${4001}/graphql`, 12 | source: './services/my-subgraph/schema.graphql', 13 | }), 14 | transforms: [ 15 | createPrefixTransform({ 16 | value: 'test_', 17 | includeRootOperations: true, 18 | }), 19 | ], 20 | }, 21 | ], 22 | }); 23 | -------------------------------------------------------------------------------- /examples/subscriptions-with-transforms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/subscriptions-with-transforms", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "graphql": "16.11.0", 7 | "graphql-sse": "^2.5.3", 8 | "graphql-yoga": "^5.13.5", 9 | "tslib": "^2.8.1", 10 | "@graphql-hive/gateway": "^1.15.0" 11 | }, 12 | "devDependencies": { 13 | "tsx": "^4.19.3" 14 | }, 15 | "overrides": { 16 | "esbuild": "^0.25.4" 17 | }, 18 | "scripts": { 19 | "service:my-subgraph": "tsx services/my-subgraph/index.ts", 20 | "compose": "mesh-compose -o supergraph.graphql", 21 | "gateway": "hive-gateway supergraph" 22 | } 23 | } -------------------------------------------------------------------------------- /examples/subscriptions-with-transforms/services/my-subgraph/schema.graphql: -------------------------------------------------------------------------------- 1 | type Query { 2 | hello: String 3 | } 4 | 5 | type Subscription { 6 | countdown(from: Int!): Int! 7 | } 8 | -------------------------------------------------------------------------------- /examples/type-merging-batching/.codesandbox/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "setupTasks": [ 3 | { 4 | "name": "Install", 5 | "command": "npm i" 6 | }, 7 | { 8 | "name": "Start service authors", 9 | "command": "nohup npm run service:authors &> service-authors.out &" 10 | }, 11 | { 12 | "name": "Wait for service authors", 13 | "command": "curl --retry-connrefused --retry 10 --retry-delay 3 http://0.0.0.0:4001" 14 | }, 15 | { 16 | "name": "Start service books", 17 | "command": "nohup npm run service:books &> service-books.out &" 18 | }, 19 | { 20 | "name": "Wait for service books", 21 | "command": "curl --retry-connrefused --retry 10 --retry-delay 3 http://0.0.0.0:4002" 22 | }, 23 | { 24 | "name": "Compose", 25 | "command": "npm run compose" 26 | } 27 | ], 28 | "tasks": { 29 | "gateway": { 30 | "name": "Hive Gateway", 31 | "runAtStart": true, 32 | "command": "npm run gateway", 33 | "preview": { 34 | "port": 4000 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /examples/type-merging-batching/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "image": "mcr.microsoft.com/devcontainers/javascript-node:20" 4 | } -------------------------------------------------------------------------------- /examples/type-merging-batching/example.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/examples/type-merging-batching/example.tar.gz -------------------------------------------------------------------------------- /examples/type-merging-batching/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/type-merging-batching", 3 | "private": true, 4 | "dependencies": { 5 | "@graphql-mesh/compose-cli": "^1.4.1", 6 | "graphql": "^16.9.0", 7 | "graphql-yoga": "^5.13.5", 8 | "tslib": "^2.8.1", 9 | "@graphql-hive/gateway": "^1.15.0" 10 | }, 11 | "devDependencies": { 12 | "tsx": "^4.19.3" 13 | }, 14 | "overrides": { 15 | "esbuild": "^0.25.4" 16 | }, 17 | "scripts": { 18 | "service:authors": "tsx services/authors.ts", 19 | "service:books": "tsx services/books.ts", 20 | "compose": "mesh-compose -o supergraph.graphql", 21 | "gateway": "hive-gateway supergraph" 22 | } 23 | } -------------------------------------------------------------------------------- /internal/e2e/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@internal/e2e", 3 | "private": true, 4 | "main": "./src/index.ts", 5 | "devDependencies": { 6 | "@apollo/gateway": "^2.11.0", 7 | "@types/dockerode": "^3.3.39", 8 | "@types/node": "^22.15.29", 9 | "@whatwg-node/disposablestack": "^0.0.6", 10 | "@whatwg-node/fetch": "^0.10.8", 11 | "dockerode": "^4.0.2", 12 | "glob": "^11.0.0", 13 | "graphql": "^16.9.0", 14 | "terminate": "^2.8.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /internal/e2e/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './tenv'; 2 | export * from './timeout'; 3 | export * from './example-setup'; 4 | export * from './services/index'; 5 | -------------------------------------------------------------------------------- /internal/e2e/src/leftoverStack.ts: -------------------------------------------------------------------------------- 1 | import { trimError } from '@internal/testing'; 2 | import { 3 | AsyncDisposableStack, 4 | SuppressedError, 5 | } from '@whatwg-node/disposablestack'; 6 | import { afterAll } from 'vitest'; 7 | 8 | export let leftoverStack = new AsyncDisposableStack(); 9 | 10 | function handleSuppressedError(e: any) { 11 | let currErr = e; 12 | while (currErr instanceof SuppressedError) { 13 | if (currErr.error) { 14 | console.error(`Suppressed error`, trimError(currErr.error)); 15 | } 16 | currErr = currErr.suppressed; 17 | } 18 | if (currErr) { 19 | console.error('Failed to dispose leftover stack', trimError(currErr)); 20 | } 21 | } 22 | 23 | afterAll(async () => { 24 | try { 25 | await leftoverStack.disposeAsync(); 26 | } catch (e) { 27 | handleSuppressedError(e); 28 | } finally { 29 | leftoverStack = new AsyncDisposableStack(); 30 | } 31 | }); 32 | -------------------------------------------------------------------------------- /internal/e2e/src/services/accounts/index.ts: -------------------------------------------------------------------------------- 1 | import { startStandaloneServer } from '@apollo/server/standalone'; 2 | import { Opts } from '@internal/testing'; 3 | import { server } from './server'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | startStandaloneServer(server, { 8 | listen: { port: opts.getServicePort('accounts') }, 9 | }).catch((err) => { 10 | console.error(err); 11 | process.exit(1); 12 | }); 13 | -------------------------------------------------------------------------------- /internal/e2e/src/services/accounts/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | me: User 3 | user(id: ID!): User 4 | users: [User] 5 | } 6 | 7 | type User @key(fields: "id") { 8 | id: ID! 9 | name: String 10 | username: String 11 | } 12 | -------------------------------------------------------------------------------- /internal/e2e/src/services/index.ts: -------------------------------------------------------------------------------- 1 | export * as accounts from './accounts/server'; 2 | export * as inventory from './inventory/server'; 3 | export * as products from './products/server'; 4 | export * as reviews from './reviews/server'; 5 | -------------------------------------------------------------------------------- /internal/e2e/src/services/inventory/index.ts: -------------------------------------------------------------------------------- 1 | import { startStandaloneServer } from '@apollo/server/standalone'; 2 | import { Opts } from '@internal/testing'; 3 | import { server } from './server'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | startStandaloneServer(server, { 8 | listen: { port: opts.getServicePort('inventory') }, 9 | }).catch((err) => { 10 | console.error(err); 11 | process.exit(1); 12 | }); 13 | -------------------------------------------------------------------------------- /internal/e2e/src/services/inventory/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend type Product @key(fields: "upc") { 2 | upc: String! @external 3 | weight: Int @external 4 | price: Int @external 5 | inStock: Boolean 6 | shippingEstimate: Int @requires(fields: "price weight") 7 | } 8 | -------------------------------------------------------------------------------- /internal/e2e/src/services/products/index.ts: -------------------------------------------------------------------------------- 1 | import { startStandaloneServer } from '@apollo/server/standalone'; 2 | import { Opts } from '@internal/testing'; 3 | import { server } from './server'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | startStandaloneServer(server, { 8 | listen: { port: opts.getServicePort('products') }, 9 | }).catch((err) => { 10 | console.error(err); 11 | process.exit(1); 12 | }); 13 | -------------------------------------------------------------------------------- /internal/e2e/src/services/products/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | topProducts(first: Int = 5): [Product] 3 | } 4 | 5 | type Product @key(fields: "upc") { 6 | upc: String! 7 | name: String 8 | price: Int 9 | weight: Int 10 | } 11 | -------------------------------------------------------------------------------- /internal/e2e/src/services/reviews/index.ts: -------------------------------------------------------------------------------- 1 | import { startStandaloneServer } from '@apollo/server/standalone'; 2 | import { Opts } from '@internal/testing'; 3 | import { server } from './server'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | startStandaloneServer(server, { 8 | listen: { port: opts.getServicePort('reviews') }, 9 | }).catch((err) => { 10 | console.error(err); 11 | process.exit(1); 12 | }); 13 | -------------------------------------------------------------------------------- /internal/e2e/src/services/reviews/typeDefs.graphql: -------------------------------------------------------------------------------- 1 | type Review @key(fields: "id") { 2 | id: ID! 3 | body: String 4 | author: User @provides(fields: "username") 5 | product: Product 6 | } 7 | 8 | extend type User @key(fields: "id") { 9 | id: ID! @external 10 | username: String @external 11 | reviews: [Review] 12 | numberOfReviews: Int 13 | } 14 | 15 | extend type Product @key(fields: "upc") { 16 | upc: String! @external 17 | reviews: [Review] 18 | } 19 | -------------------------------------------------------------------------------- /internal/e2e/src/timeout.ts: -------------------------------------------------------------------------------- 1 | export const retries = 120, 2 | interval = 500, 3 | timeout = retries * interval; // 1min 4 | -------------------------------------------------------------------------------- /internal/examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@internal/examples", 3 | "type": "module", 4 | "private": true, 5 | "main": "./src/index.ts", 6 | "scripts": { 7 | "start": "tsx ./src/bin.ts" 8 | }, 9 | "devDependencies": { 10 | "@apollo/rover": "^0.32.1", 11 | "@babel/parser": "^7.27.5", 12 | "@types/jscodeshift": "^17.0.0", 13 | "@whatwg-node/disposablestack": "^0.0.6", 14 | "dedent": "^1.5.3", 15 | "esbuild": "^0.25.5", 16 | "glob": "^11.0.0", 17 | "jscodeshift": "^17.1.1", 18 | "tsx": "^4.19.2", 19 | "zod": "^3.25.51" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /internal/examples/src/bin.ts: -------------------------------------------------------------------------------- 1 | import { Opts, strToBool } from '@internal/testing'; 2 | import z from 'zod'; 3 | import { convertE2EToExample, PublishedPackages } from './convert'; 4 | 5 | const opts = Opts(process.argv); 6 | 7 | let publishedPackages: PublishedPackages | undefined; 8 | const publishedPackagesOpt = opts.get('publishedPackages'); 9 | if (publishedPackagesOpt) { 10 | try { 11 | publishedPackages = z 12 | .array( 13 | z.object({ 14 | name: z.string(), 15 | version: z.string(), 16 | }), 17 | ) 18 | .parse(JSON.parse(publishedPackagesOpt)); 19 | } catch (err) { 20 | throw new Error('Problem while parsing "publishedPackages" option', { 21 | cause: err, 22 | }); 23 | } 24 | } 25 | 26 | await convertE2EToExample({ 27 | e2e: opts.get('e2e', true), 28 | clean: strToBool(String(opts.get('clean'))), 29 | skipTest: strToBool(String(opts.get('skipTest'))), 30 | publishedPackages, 31 | }); 32 | -------------------------------------------------------------------------------- /internal/examples/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './convert'; 2 | -------------------------------------------------------------------------------- /internal/perf/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@internal/perf", 3 | "type": "module", 4 | "private": true, 5 | "main": "./src/index.ts", 6 | "dependencies": { 7 | "@memlab/core": "^1.1.39", 8 | "@memlab/heap-analysis": "^1.0.36", 9 | "@whatwg-node/promise-helpers": "^1.3.0", 10 | "canvas": "^3.1.0", 11 | "chart.js": "^4.4.7", 12 | "chartjs-plugin-trendline": "^2.1.9", 13 | "memlab": "^1.1.56", 14 | "parse-duration": "^2.0.0", 15 | "speedscope": "./speedscope-1.23.0-alpha.4.tgz", 16 | "ws": "^8.18.0" 17 | }, 18 | "devDependencies": { 19 | "@types/k6": "^1.0.0", 20 | "@types/ws": "^8.5.12" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /internal/perf/speedscope-1.23.0-alpha.4.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-hive/gateway/6df5dc0e35cff60e2243c972fc386d20b739ad10/internal/perf/speedscope-1.23.0-alpha.4.tgz -------------------------------------------------------------------------------- /internal/perf/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './loadtest'; 2 | export * from './heap'; 3 | export * from './inspector'; 4 | -------------------------------------------------------------------------------- /internal/proc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@internal/proc", 3 | "type": "module", 4 | "private": true, 5 | "main": "./src/index.ts" 6 | } 7 | -------------------------------------------------------------------------------- /internal/testing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@internal/testing", 3 | "type": "module", 4 | "private": true, 5 | "main": "./src/index.ts", 6 | "exports": { 7 | ".": "./src/index.ts", 8 | "./fixtures/schemas": "./fixtures/schemas.ts", 9 | "./vitest": "./src/vitest.ts", 10 | "./to-be-similar-string": "./src/to-be-similar-string.ts", 11 | "./to-be-similar-gql-doc": "./src/to-be-similar-gql-doc.ts" 12 | }, 13 | "devDependencies": { 14 | "@graphql-hive/pubsub": "workspace:*", 15 | "@graphql-mesh/types": "^0.104.0", 16 | "@graphql-tools/utils": "^10.7.2", 17 | "@types/node": "^22.15.29", 18 | "@whatwg-node/disposablestack": "^0.0.6", 19 | "@whatwg-node/fetch": "^0.10.8", 20 | "@whatwg-node/promise-helpers": "^1.2.5", 21 | "graphql": "^16.10.0", 22 | "jest-leak-detector": "29.7.0", 23 | "ws": "^8.18.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /internal/testing/src/benchConfig.ts: -------------------------------------------------------------------------------- 1 | import { BenchOptions } from 'vitest'; 2 | 3 | const isCI = !!process.env['CI']; 4 | 5 | const duration = useNumberEnv('BENCH_DURATION', isCI ? 30000 : 3000); 6 | const warmupTime = useNumberEnv('BENCH_WARMUP_TIME', isCI ? 5000 : 300); 7 | const warmupIterations = useNumberEnv('BENCH_WARMUP_ITERATIONS', isCI ? 10 : 3); 8 | 9 | export const benchConfig: BenchOptions = { 10 | time: duration, 11 | warmupTime, 12 | warmupIterations, 13 | throws: true, 14 | }; 15 | 16 | export function useNumberEnv(envName: string, defaultValue: number): number { 17 | const value = process.env[envName]; 18 | if (!value) { 19 | return defaultValue; 20 | } 21 | return parseInt(value, 10); 22 | } 23 | -------------------------------------------------------------------------------- /internal/testing/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './server'; 2 | export * from './env'; 3 | export * from './getLocalhost'; 4 | export * from './opts'; 5 | export * from './assertions'; 6 | export * from './benchConfig'; 7 | export * from './trimError'; 8 | export * from './composeLocalSchemasWithApollo'; 9 | export * from './graphql'; 10 | export * from '@whatwg-node/promise-helpers'; 11 | -------------------------------------------------------------------------------- /internal/testing/src/trimError.ts: -------------------------------------------------------------------------------- 1 | export function trimError(error: any) { 2 | return error.toString().split('(data:text/javascript')[0]; 3 | } 4 | -------------------------------------------------------------------------------- /internal/testing/src/vitest.ts: -------------------------------------------------------------------------------- 1 | const cancelledCtrl = new AbortController(); 2 | 3 | // @ts-expect-error https://github.com/vitest-dev/vitest/issues/7647#issuecomment-2712223721 4 | globalThis.__vitest_worker__?.onCancel // new line to type-check rest 5 | .then(() => cancelledCtrl.abort('Test run cancelled')); 6 | 7 | /** Worker's test run has been cancelled by the user. Using `Q` or a single `CTRL+C`. */ 8 | export const cancelledSignal = cancelledCtrl.signal; 9 | -------------------------------------------------------------------------------- /packages/batch-delegate/README.md: -------------------------------------------------------------------------------- 1 | Check API Reference for more information about this package; 2 | https://www.graphql-tools.com/docs/api/modules/batch_delegate_src 3 | 4 | You can also learn more about Batch Delegation in this chapter; 5 | https://www.graphql-tools.com/docs/stitch-schema-extensions #batch-delegation 6 | -------------------------------------------------------------------------------- /packages/batch-delegate/src/batchDelegateToSchema.ts: -------------------------------------------------------------------------------- 1 | import { getLoader } from './getLoader.js'; 2 | import { BatchDelegateOptions } from './types.js'; 3 | 4 | export function batchDelegateToSchema( 5 | options: BatchDelegateOptions, 6 | ): any { 7 | const key = options.key; 8 | if (key == null) { 9 | return null; 10 | } else if (Array.isArray(key) && !key.length) { 11 | return []; 12 | } 13 | const loader = getLoader(options); 14 | return Array.isArray(key) ? loader.loadMany(key) : loader.load(key); 15 | } 16 | -------------------------------------------------------------------------------- /packages/batch-delegate/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './batchDelegateToSchema.js'; 2 | export * from './createBatchDelegateFn.js'; 3 | 4 | export * from './types.js'; 5 | -------------------------------------------------------------------------------- /packages/batch-execute/README.md: -------------------------------------------------------------------------------- 1 | Check API Reference for more information about this package; 2 | https://www.graphql-tools.com/docs/api/modules/batch_execute_src 3 | 4 | You can also learn more about Batch Delegation in this chapter; 5 | https://www.graphql-tools.com/docs/stitch-schema-extensions#batch-delegation 6 | -------------------------------------------------------------------------------- /packages/batch-execute/src/getBatchingExecutor.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionRequest, Executor, memoize2of4 } from '@graphql-tools/utils'; 2 | import DataLoader from 'dataloader'; 3 | import { createBatchingExecutor } from './createBatchingExecutor.js'; 4 | 5 | export const getBatchingExecutor = memoize2of4(function getBatchingExecutor( 6 | _context: Record, 7 | executor: Executor, 8 | dataLoaderOptions?: DataLoader.Options | undefined, 9 | extensionsReducer?: 10 | | undefined 11 | | (( 12 | mergedExtensions: Record, 13 | request: ExecutionRequest, 14 | ) => Record), 15 | ): Executor { 16 | return createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/batch-execute/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './createBatchingExecutor.js'; 2 | export * from './getBatchingExecutor.js'; 3 | -------------------------------------------------------------------------------- /packages/delegate/README.md: -------------------------------------------------------------------------------- 1 | Check API Reference for more information about this package; 2 | https://www.graphql-tools.com/docs/api/modules/delegate_src 3 | 4 | You can also learn more about Schema Delegation in this chapter; 5 | https://www.graphql-tools.com/docs/schema-delegation 6 | -------------------------------------------------------------------------------- /packages/delegate/src/applySchemaTransforms.ts: -------------------------------------------------------------------------------- 1 | import { memoize2 } from '@graphql-tools/utils'; 2 | import { GraphQLSchema } from 'graphql'; 3 | import { SubschemaConfig } from './types.js'; 4 | 5 | // TODO: Instead of memoization, we can make sure that this isn't called multiple times 6 | export const applySchemaTransforms = memoize2(function applySchemaTransforms( 7 | originalWrappingSchema: GraphQLSchema, 8 | subschemaConfig: SubschemaConfig, 9 | ): GraphQLSchema { 10 | const schemaTransforms = subschemaConfig.transforms; 11 | 12 | if (schemaTransforms == null) { 13 | return originalWrappingSchema; 14 | } 15 | 16 | return schemaTransforms.reduce( 17 | (schema: GraphQLSchema, transform) => 18 | transform.transformSchema?.(schema, subschemaConfig) || schema, 19 | originalWrappingSchema, 20 | ); 21 | }); 22 | -------------------------------------------------------------------------------- /packages/delegate/src/getDocumentMetadata.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DocumentNode, 3 | FragmentDefinitionNode, 4 | Kind, 5 | OperationDefinitionNode, 6 | } from 'graphql'; 7 | 8 | export function getDocumentMetadata(document: DocumentNode): { 9 | operations: Array; 10 | fragments: Array; 11 | fragmentNames: Set; 12 | } { 13 | const operations: OperationDefinitionNode[] = []; 14 | const fragments: FragmentDefinitionNode[] = []; 15 | const fragmentNames = new Set(); 16 | for (let i = 0; i < document.definitions.length; i++) { 17 | const def = document.definitions[i]; 18 | 19 | if (def?.kind === Kind.FRAGMENT_DEFINITION) { 20 | fragments.push(def); 21 | fragmentNames.add(def.name.value); 22 | } else if (def?.kind === Kind.OPERATION_DEFINITION) { 23 | operations.push(def); 24 | } 25 | } 26 | 27 | return { 28 | operations, 29 | fragments, 30 | fragmentNames, 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /packages/delegate/src/getTypeInfo.ts: -------------------------------------------------------------------------------- 1 | import { Maybe, memoize1, memoize2 } from '@graphql-tools/utils'; 2 | import { GraphQLSchema, GraphQLType, TypeInfo, versionInfo } from 'graphql'; 3 | 4 | export const getTypeInfo = memoize1(function getTypeInfo( 5 | schema: GraphQLSchema, 6 | ) { 7 | return new TypeInfo(schema); 8 | }); 9 | 10 | export const getTypeInfoWithType = memoize2(function getTypeInfoWithType( 11 | schema: GraphQLSchema, 12 | type: Maybe, 13 | ) { 14 | return versionInfo.major < 16 15 | ? new TypeInfo(schema, undefined, type as any) 16 | : new TypeInfo(schema, type as any); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/delegate/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Subschema.js'; 2 | export * from './Transformer.js'; 3 | export * from './applySchemaTransforms.js'; 4 | export * from './createRequest.js'; 5 | export * from './defaultMergedResolver.js'; 6 | export * from './delegateToSchema.js'; 7 | export * from './mergeFields.js'; 8 | export * from './resolveExternalValue.js'; 9 | export * from './subschemaConfig.js'; 10 | export * from './types.js'; 11 | export * from './extractUnavailableFields.js'; 12 | export * from './leftOver.js'; 13 | export * from './symbols.js'; 14 | export * from './getTypeInfo.js'; 15 | export * from './isPrototypePollutingKey.js'; 16 | -------------------------------------------------------------------------------- /packages/delegate/src/isPrototypePollutingKey.ts: -------------------------------------------------------------------------------- 1 | const prototypePollutingKeys = [ 2 | '__proto__', 3 | 'constructor', 4 | 'prototype', 5 | ] as const; 6 | 7 | type PrototypePollutingKey = (typeof prototypePollutingKeys)[number]; 8 | 9 | export function isPrototypePollutingKey( 10 | key: string, 11 | ): key is PrototypePollutingKey { 12 | // @ts-expect-error - typings are incorrect 13 | return prototypePollutingKeys.includes(key); 14 | } 15 | -------------------------------------------------------------------------------- /packages/delegate/src/symbols.ts: -------------------------------------------------------------------------------- 1 | export const UNPATHED_ERRORS_SYMBOL = Symbol.for('subschemaErrors'); 2 | export const OBJECT_SUBSCHEMA_SYMBOL = Symbol.for('initialSubschema'); 3 | export const FIELD_SUBSCHEMA_MAP_SYMBOL = Symbol.for('subschemaMap'); 4 | -------------------------------------------------------------------------------- /packages/executors/http/src/isGraphQLUpload.ts: -------------------------------------------------------------------------------- 1 | import type { Readable } from 'stream'; 2 | 3 | interface GraphQLUpload { 4 | filename: string; 5 | mimetype: string; 6 | createReadStream: () => Readable; 7 | } 8 | 9 | export function isGraphQLUpload(upload: any): upload is GraphQLUpload { 10 | return typeof upload.createReadStream === 'function'; 11 | } 12 | -------------------------------------------------------------------------------- /packages/executors/http/src/isLiveQueryOperationDefinitionNode.ts: -------------------------------------------------------------------------------- 1 | import { memoize1 } from '@graphql-tools/utils'; 2 | import { OperationDefinitionNode } from 'graphql'; 3 | 4 | export const isLiveQueryOperationDefinitionNode = memoize1( 5 | function isLiveQueryOperationDefinitionNode(node: OperationDefinitionNode) { 6 | return ( 7 | node.operation === 'query' && 8 | node.directives?.some((directive) => directive.name.value === 'live') 9 | ); 10 | }, 11 | ); 12 | -------------------------------------------------------------------------------- /packages/federation/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './managed-federation.js'; 2 | export * from './supergraph.js'; 3 | export * from './utils.js'; 4 | -------------------------------------------------------------------------------- /packages/federation/tests/.gitignore: -------------------------------------------------------------------------------- 1 | ignored-hidden 2 | -------------------------------------------------------------------------------- /packages/federation/tests/fixtures/.gitignore: -------------------------------------------------------------------------------- 1 | federation-compatibility 2 | -------------------------------------------------------------------------------- /packages/federation/tests/fixtures/gateway/supergraph.ts: -------------------------------------------------------------------------------- 1 | import { buildSubgraphSchema } from '@apollo/subgraph'; 2 | import { accounts, inventory, products, reviews } from '@internal/e2e'; 3 | import { composeLocalSchemasWithApollo } from '@internal/testing'; 4 | import { DocumentNode, GraphQLSchema } from 'graphql'; 5 | 6 | const services = { 7 | accounts, 8 | inventory, 9 | products, 10 | reviews, 11 | } as const; 12 | 13 | export interface ServiceInput { 14 | name: string; 15 | typeDefs: DocumentNode; 16 | schema: GraphQLSchema; 17 | } 18 | 19 | export function getServiceInputs() { 20 | return Object.entries(services).map(([name, module]) => ({ 21 | name, 22 | typeDefs: module.typeDefs, 23 | schema: buildSubgraphSchema(module), 24 | })); 25 | } 26 | 27 | export async function getSupergraph() { 28 | return composeLocalSchemasWithApollo(getServiceInputs()); 29 | } 30 | -------------------------------------------------------------------------------- /packages/fusion-runtime/scripts/replace-import-with-require.mjs: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs'; 2 | 3 | const cjsFile = './dist/index.cjs'; 4 | const fileContent = fs.readFileSync(cjsFile, 'utf8'); 5 | const newContent = fileContent.replace( 6 | 'import(moduleName)', 7 | 'require(moduleName)', 8 | ); 9 | fs.writeFileSync(cjsFile, newContent, 'utf8'); 10 | -------------------------------------------------------------------------------- /packages/fusion-runtime/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './utils'; 2 | export * from './unifiedGraphManager'; 3 | export * from './federation/supergraph'; 4 | export * from './federation/subgraph'; 5 | export * from './executor'; 6 | -------------------------------------------------------------------------------- /packages/fusion-runtime/tests/__snapshots__/runtime.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`onDelegationPlanHook should be called with the plan: onDelegationPlanPayload.fieldNodes[0] 1`] = ` 4 | "author { 5 | id 6 | name 7 | }" 8 | `; 9 | 10 | exports[`onDelegationPlanHook should be called with the plan: onDelegationPlanPayload.subgraph 1`] = `"posts"`; 11 | 12 | exports[`onDelegationPlanHook should be called with the plan: onDelegationPlanPayload.supergraph 1`] = ` 13 | "schema { 14 | query: Query 15 | } 16 | 17 | type Query { 18 | posts: [Post] 19 | users: [User] 20 | } 21 | 22 | type Post { 23 | id: ID! 24 | title: String 25 | author: User 26 | } 27 | 28 | type User { 29 | id: ID! 30 | name: String 31 | }" 32 | `; 33 | 34 | exports[`onDelegationPlanHook should be called with the plan: onDelegationPlanPayload.typeName 1`] = `"User"`; 35 | 36 | exports[`onDelegationPlanHook should be called with the plan: onDelegationPlanPayload.variables 1`] = `{}`; 37 | -------------------------------------------------------------------------------- /packages/gateway/bun_e2e.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gateway_e2e_base-bun 2 | 3 | # install the extra depdenencies under the workspace node_modules making sure 4 | # that modules installed by the user work as expected (extending the image) 5 | # COPY --chown=bun bundle/e2e/package.json package.json - not necessary in bun since `bun install` wont clean the node_modules 6 | COPY --chown=bun bundle/e2e/node_modules node_modules 7 | -------------------------------------------------------------------------------- /packages/gateway/node_e2e.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gateway_e2e_base 2 | 3 | # install the extra depdenencies under the workspace node_modules making sure 4 | # that modules installed by the user work as expected (extending the image) 5 | COPY --chown=node bundle/e2e/package.json package.json 6 | COPY --chown=node bundle/e2e/node_modules node_modules 7 | -------------------------------------------------------------------------------- /packages/gateway/scripts/postject.d.ts: -------------------------------------------------------------------------------- 1 | // https://github.com/nodejs/postject/pull/99 2 | 3 | declare module 'postject' { 4 | export interface InjectOptions { 5 | /** 6 | * @default '__POSTJECT' 7 | */ 8 | machoSegmentName?: string; 9 | /** 10 | * @default false 11 | */ 12 | overwrite?: boolean; 13 | /** 14 | * @default "POSTJECT_SENTINEL_fce680ab2cc467b6e072b8b5df1996b2" 15 | */ 16 | sentinelFuse?: string; 17 | } 18 | 19 | export function inject( 20 | filename: string, 21 | resourceName: string, 22 | resourceData: Buffer, 23 | options?: InjectOptions, 24 | ): Promise; 25 | } 26 | -------------------------------------------------------------------------------- /packages/gateway/sea-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "bundle/hive-gateway.cjs", 3 | "output": "sea-prep.blob", 4 | "disableExperimentalSEAWarning": true, 5 | "useCodeCache": true, 6 | "assets": { 7 | "node_modules.zip": "bundle/node_modules.zip" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/gateway/src/bin.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import 'dotenv/config'; // inject dotenv options to process.env 3 | 4 | import module from 'node:module'; 5 | import type { InitializeData } from '@graphql-hive/importer/hooks'; 6 | import { getDefaultLogger } from '../../runtime/src/getDefaultLogger'; 7 | import { enableModuleCachingIfPossible, handleNodeWarnings, run } from './cli'; 8 | 9 | // @inject-version globalThis.__VERSION__ here 10 | 11 | module.register('@graphql-hive/importer/hooks', { 12 | parentURL: 13 | // @ts-ignore bob will complain when bundling for cjs 14 | import.meta.url, 15 | data: { 16 | packedDepsPath: globalThis.__PACKED_DEPS_PATH__ || '', 17 | } satisfies InitializeData, 18 | }); 19 | 20 | enableModuleCachingIfPossible(); 21 | handleNodeWarnings(); 22 | 23 | const log = getDefaultLogger(); 24 | 25 | run({ log }).catch((err) => { 26 | log.error(err); 27 | process.exit(1); 28 | }); 29 | -------------------------------------------------------------------------------- /packages/gateway/src/commands/handleLoggingOption.ts: -------------------------------------------------------------------------------- 1 | import { 2 | handleLoggingConfig as handleLoggingConfigRuntime, 3 | LogLevel, 4 | } from '@graphql-hive/gateway-runtime'; 5 | import { Logger } from '@graphql-mesh/types'; 6 | import { CLIContext } from '..'; 7 | 8 | export function handleLoggingConfig( 9 | loggingConfig: 10 | | boolean 11 | | Logger 12 | | LogLevel 13 | | keyof typeof LogLevel 14 | | undefined, 15 | ctx: CLIContext, 16 | ) { 17 | ctx.log = handleLoggingConfigRuntime(loggingConfig, ctx.log); 18 | } 19 | -------------------------------------------------------------------------------- /packages/gateway/src/commands/index.ts: -------------------------------------------------------------------------------- 1 | import type { AddCommand } from '../cli'; 2 | import { addCommand as addProxyCommand } from './proxy'; 3 | import { addCommand as addSubgraphCommand } from './subgraph'; 4 | import { addCommand as addSupergraphCommand } from './supergraph'; 5 | 6 | export const addCommands: AddCommand = (ctx, cli) => { 7 | addSupergraphCommand(ctx, cli); 8 | addSubgraphCommand(ctx, cli); 9 | addProxyCommand(ctx, cli); 10 | }; 11 | -------------------------------------------------------------------------------- /packages/gateway/src/getMaxConcurrency.ts: -------------------------------------------------------------------------------- 1 | import { availableParallelism, freemem } from 'node:os'; 2 | 3 | function getFreeMemInGb() { 4 | return freemem() / 1024 ** 2; 5 | } 6 | 7 | function getMaxConcurrencyPerMem() { 8 | return parseInt(String(getFreeMemInGb())); 9 | } 10 | 11 | function getMaxConcurrencyPerCpu() { 12 | return availableParallelism(); 13 | } 14 | 15 | export function getMaxConcurrency() { 16 | const result = Math.min(getMaxConcurrencyPerMem(), getMaxConcurrencyPerCpu()); 17 | if (result < 1) { 18 | return 1; 19 | } 20 | return result; 21 | } 22 | -------------------------------------------------------------------------------- /packages/gateway/src/globals.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | 3 | declare global { 4 | /** 5 | * Available ONLY in SEA environment. 6 | * See `scripts/install-sea-packed-deps.cjs` and `rollup.binary.config.js` 7 | */ 8 | var __PACKED_DEPS_PATH__: string | undefined; 9 | /** Gets injected during build by `scripts/inject-version.ts`. */ 10 | var __VERSION__: string | undefined; 11 | } 12 | -------------------------------------------------------------------------------- /packages/importer/README.md: -------------------------------------------------------------------------------- 1 | # @graphql-hive/importer 2 | 3 | Used to improve Hive's importing capabilities allowing it to parse TypeScript files. 4 | 5 | Please note that `get-tsconfig` and `sucrase` are **intentionally** inside devDependencies at the [package.json](/packages/mporter/package.json) because we want to bundle them in. 6 | 7 | [pkgroll will bundle all devDependencies that are used in the source code.](https://github.com/privatenumber/pkgroll?tab=readme-ov-file#dependency-bundling--externalization) 8 | -------------------------------------------------------------------------------- /packages/importer/src/debug.ts: -------------------------------------------------------------------------------- 1 | export const isDebug = ['importer'].includes(String(process.env['DEBUG'])); 2 | 3 | export function debug(message: string) { 4 | if (isDebug) { 5 | process.stderr.write( 6 | `${JSON.stringify({ 7 | name: 'importer', 8 | level: 'debug', 9 | message, 10 | })}\n`, 11 | ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/importer/src/index.ts: -------------------------------------------------------------------------------- 1 | export { transpileTypeScriptFile } from './transpile'; 2 | -------------------------------------------------------------------------------- /packages/importer/tests/fixtures/basic.cts: -------------------------------------------------------------------------------- 1 | const str: string = 'ing'; 2 | module.exports = { str }; 3 | -------------------------------------------------------------------------------- /packages/importer/tests/fixtures/basic.ts: -------------------------------------------------------------------------------- 1 | export const str: string = 'ing'; 2 | -------------------------------------------------------------------------------- /packages/importer/tests/fixtures/syntax-error.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck -- syntax error intentionally 2 | const str ing: string = '?'; 3 | -------------------------------------------------------------------------------- /packages/plugins/aws-sigv4/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './plugin'; 2 | export * from './types'; 3 | -------------------------------------------------------------------------------- /packages/plugins/deduplicate-request/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @graphql-hive/plugin-deduplicate-request 2 | 3 | ## 1.0.0 4 | 5 | ### Major Changes 6 | 7 | - [#1088](https://github.com/graphql-hive/gateway/pull/1088) [`305dbc4`](https://github.com/graphql-hive/gateway/commit/305dbc4ce08f53508f400e8e2610cb32e68002bc) Thanks [@enisdenjo](https://github.com/enisdenjo)! - Request deduplicate plugin for Hive Gateway 8 | 9 | ### Patch Changes 10 | 11 | - [#1095](https://github.com/graphql-hive/gateway/pull/1095) [`2dc5fd8`](https://github.com/graphql-hive/gateway/commit/2dc5fd89a292811e7ea845d14e0ddacecfa83e9f) Thanks [@enisdenjo](https://github.com/enisdenjo)! - Don't deduplicate failing (non-2XX status code) requests 12 | -------------------------------------------------------------------------------- /packages/plugins/opentelemetry/src/attributes.ts: -------------------------------------------------------------------------------- 1 | // HTTP/network attributes 2 | export { 3 | SEMATTRS_HTTP_CLIENT_IP, 4 | SEMATTRS_HTTP_HOST, 5 | SEMATTRS_HTTP_METHOD, 6 | SEMATTRS_HTTP_ROUTE, 7 | SEMATTRS_HTTP_SCHEME, 8 | SEMATTRS_HTTP_SERVER_NAME, 9 | SEMATTRS_HTTP_STATUS_CODE, 10 | SEMATTRS_HTTP_URL, 11 | SEMATTRS_HTTP_USER_AGENT, 12 | SEMATTRS_NET_HOST_NAME, 13 | ATTR_SERVICE_NAME as SEMRESATTRS_SERVICE_NAME, 14 | ATTR_SERVICE_VERSION, 15 | } from '@opentelemetry/semantic-conventions'; 16 | 17 | // GraphQL-specific attributes 18 | // Based on https://opentelemetry.io/docs/specs/semconv/attributes-registry/graphql/ 19 | export const SEMATTRS_GRAPHQL_DOCUMENT = 'graphql.document'; 20 | export const SEMATTRS_GRAPHQL_OPERATION_TYPE = 'graphql.operation.type'; 21 | export const SEMATTRS_GRAPHQL_OPERATION_NAME = 'graphql.operation.name'; 22 | export const SEMATTRS_GRAPHQL_ERROR_COUNT = 'graphql.error.count'; 23 | 24 | // Gateway-specific attributes 25 | export const SEMATTRS_GATEWAY_UPSTREAM_SUBGRAPH_NAME = 26 | 'gateway.upstream.subgraph.name'; 27 | -------------------------------------------------------------------------------- /packages/plugins/opentelemetry/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './processors'; 2 | export { 3 | useOpenTelemetry, 4 | type OpenTelemetryGatewayPluginOptions as OpenTelemetryMeshPluginOptions, 5 | } from './plugin'; 6 | -------------------------------------------------------------------------------- /packages/pubsub/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @graphql-hive/pubsub 2 | 3 | ## 1.0.0 4 | 5 | ### Major Changes 6 | 7 | - [#933](https://github.com/graphql-hive/gateway/pull/933) [`a374bfc`](https://github.com/graphql-hive/gateway/commit/a374bfcf4309f5953b8c8304fba8e079b6f6b6dc) Thanks [@enisdenjo](https://github.com/enisdenjo)! - Introduce Hive Gateway PubSub with hardened memory safety 8 | -------------------------------------------------------------------------------- /packages/pubsub/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './pubsub'; 2 | -------------------------------------------------------------------------------- /packages/runtime/scripts/generate-landing-page-html.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'node:fs'; 2 | import * as path from 'node:path'; 3 | import { fileURLToPath } from 'node:url'; 4 | import { minify } from 'html-minifier-terser'; 5 | 6 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); 7 | 8 | const minified = await minify( 9 | fs.readFileSync( 10 | path.join(__dirname, '..', 'src', 'landing-page.html'), 11 | 'utf-8', 12 | ), 13 | { 14 | minifyJS: true, 15 | useShortDoctype: false, 16 | removeAttributeQuotes: true, 17 | collapseWhitespace: true, 18 | minifyCSS: true, 19 | }, 20 | ); 21 | 22 | await fs.promises.writeFile( 23 | path.join(__dirname, '../src/landing-page-html.ts'), 24 | `export default ${JSON.stringify(minified)}`, 25 | ); 26 | -------------------------------------------------------------------------------- /packages/runtime/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './createGatewayRuntime'; 2 | export { LogLevel, DefaultLogger } from '@graphql-mesh/utils'; 3 | export { JSONLogger } from '@graphql-hive/logger-json'; 4 | export type * from './types'; 5 | export * from './plugins/useCustomFetch'; 6 | export * from './plugins/useStaticFiles'; 7 | export * from './getProxyExecutor'; 8 | export * from './plugins/usePropagateHeaders'; 9 | export * from '@whatwg-node/disposablestack'; 10 | export type { ResolveUserFn, ValidateUserFn } from '@envelop/generic-auth'; 11 | export * from '@graphql-mesh/hmac-upstream-signature'; 12 | export { 13 | getSdkRequesterForUnifiedGraph, 14 | getExecutorForUnifiedGraph, 15 | } from '@graphql-mesh/fusion-runtime'; 16 | export { useUpstreamRetry } from './plugins/useUpstreamRetry'; 17 | export { useUpstreamTimeout } from './plugins/useUpstreamTimeout'; 18 | export { getGraphQLWSOptions } from './getGraphQLWSOptions'; 19 | export * from './getDefaultLogger'; 20 | -------------------------------------------------------------------------------- /packages/runtime/src/plugins/useCustomAgent.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/no-nodejs-modules 2 | import type { Agent as HttpAgent } from 'node:http'; 3 | // eslint-disable-next-line import/no-nodejs-modules 4 | import type { Agent as HttpsAgent } from 'node:https'; 5 | import type { OnFetchHookPayload } from '@graphql-mesh/types'; 6 | import type { GatewayContext, GatewayPlugin } from '../types'; 7 | 8 | export type AgentFactory = ( 9 | payload: OnFetchHookPayload< 10 | Partial & GatewayContext & Record 11 | >, 12 | ) => HttpAgent | HttpsAgent | false | undefined; 13 | 14 | export function useCustomAgent>( 15 | agentFactory: AgentFactory, 16 | ): GatewayPlugin { 17 | return { 18 | onFetch(payload) { 19 | const agent = agentFactory(payload); 20 | if (agent != null) { 21 | payload.setOptions({ 22 | ...payload.options, 23 | // @ts-expect-error - `agent` is there 24 | agent, 25 | }); 26 | } 27 | }, 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /packages/runtime/src/plugins/useCustomFetch.ts: -------------------------------------------------------------------------------- 1 | import type { MeshFetch } from '@graphql-mesh/types'; 2 | import type { GatewayPlugin } from '../types'; 3 | 4 | export function useCustomFetch(fetch: MeshFetch): GatewayPlugin { 5 | return { 6 | onFetch({ setFetchFn }) { 7 | setFetchFn(fetch); 8 | }, 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /packages/runtime/tests/__snapshots__/hive.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Hive CDN respects env vars: hive-cdn 1`] = ` 4 | "type Query { 5 | foo: String 6 | }" 7 | `; 8 | -------------------------------------------------------------------------------- /packages/signal/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @graphql-hive/signal 2 | 3 | ## 1.0.0 4 | 5 | ### Major Changes 6 | 7 | - [#922](https://github.com/graphql-hive/gateway/pull/922) [`c9cd206`](https://github.com/graphql-hive/gateway/commit/c9cd20666a740514a5c17ecd6d0c000ad0dd7106) Thanks [@enisdenjo](https://github.com/enisdenjo)! - Ponyfill AbortSignal.any without leaks 8 | -------------------------------------------------------------------------------- /packages/signal/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './abortSignalAny'; 2 | -------------------------------------------------------------------------------- /packages/stitch/README.md: -------------------------------------------------------------------------------- 1 | Check API Reference for more information about this package; 2 | https://www.graphql-tools.com/docs/api/modules/stitch_src 3 | 4 | You can also learn more about Schema Stitching in this chapter; 5 | https://www.graphql-tools.com/docs/stitch-combining-schemas 6 | -------------------------------------------------------------------------------- /packages/stitch/src/index.ts: -------------------------------------------------------------------------------- 1 | export { stitchSchemas } from './stitchSchemas.js'; 2 | export { createMergedTypeResolver } from './createMergedTypeResolver.js'; 3 | export { forwardArgsToSelectionSet } from './selectionSetArgs.js'; 4 | 5 | export * from './subschemaConfigTransforms/index.js'; 6 | export * from './types.js'; 7 | export * from './relay.js'; 8 | export * from './executor.js'; 9 | export { getDefaultFieldConfigMerger } from './mergeCandidates.js'; 10 | export { calculateSelectionScore } from './createDelegationPlanBuilder.js'; 11 | -------------------------------------------------------------------------------- /packages/stitch/src/subschemaConfigTransforms/index.ts: -------------------------------------------------------------------------------- 1 | export { isolateComputedFieldsTransformer } from './isolateComputedFieldsTransformer.js'; 2 | export { splitMergedTypeEntryPointsTransformer } from './splitMergedTypeEntryPointsTransformer.js'; 3 | -------------------------------------------------------------------------------- /packages/stitching-directives/README.md: -------------------------------------------------------------------------------- 1 | Check API Reference for more information about this package; 2 | https://www.graphql-tools.com/docs/api/modules/stitching_directives_src 3 | 4 | You can also learn more about Schema Stitching Directives in this chapter; 5 | https://www.graphql-tools.com/docs/stitch-directives-sdl 6 | -------------------------------------------------------------------------------- /packages/stitching-directives/src/defaultStitchingDirectiveOptions.ts: -------------------------------------------------------------------------------- 1 | import { StitchingDirectivesFinalOptions } from './types.js'; 2 | 3 | export const defaultStitchingDirectiveOptions: StitchingDirectivesFinalOptions = 4 | { 5 | keyDirectiveName: 'key', 6 | computedDirectiveName: 'computed', 7 | canonicalDirectiveName: 'canonical', 8 | mergeDirectiveName: 'merge', 9 | pathToDirectivesInExtensions: ['directives'], 10 | }; 11 | -------------------------------------------------------------------------------- /packages/stitching-directives/src/getSourcePaths.ts: -------------------------------------------------------------------------------- 1 | import { SelectionSetNode, TypeNameMetaFieldDef } from 'graphql'; 2 | import { pathsFromSelectionSet } from './pathsFromSelectionSet.js'; 3 | import { MappingInstruction } from './types.js'; 4 | 5 | export function getSourcePaths( 6 | mappingInstructions: Array, 7 | selectionSet?: SelectionSetNode, 8 | ): Array> { 9 | const sourcePaths: Array> = []; 10 | for (const mappingInstruction of mappingInstructions) { 11 | const { sourcePath } = mappingInstruction; 12 | if (sourcePath.length) { 13 | sourcePaths.push(sourcePath); 14 | continue; 15 | } 16 | 17 | if (selectionSet == null) { 18 | continue; 19 | } 20 | 21 | const paths = pathsFromSelectionSet(selectionSet); 22 | for (const path of paths) { 23 | sourcePaths.push(path); 24 | } 25 | 26 | sourcePaths.push([TypeNameMetaFieldDef.name]); 27 | } 28 | 29 | return sourcePaths; 30 | } 31 | -------------------------------------------------------------------------------- /packages/stitching-directives/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './stitchingDirectives.js'; 2 | export * from './types.js'; 3 | export * from './federationToStitchingSDL.js'; 4 | -------------------------------------------------------------------------------- /packages/stitching-directives/tests/pathsFromSelectionSets.test.ts: -------------------------------------------------------------------------------- 1 | import { parseSelectionSet } from '@graphql-tools/utils'; 2 | import { describe, expect, test } from 'vitest'; 3 | import { pathsFromSelectionSet } from '../src/pathsFromSelectionSet.js'; 4 | 5 | describe('can convert selectionSet hints to paths', () => { 6 | test('can convert a simple selection set', () => { 7 | const selectionSet = parseSelectionSet(`{ test }`); 8 | const result = pathsFromSelectionSet(selectionSet); 9 | expect(result).toEqual([['test']]); 10 | }); 11 | 12 | test('can convert a complex selection set', () => { 13 | const selectionSet = parseSelectionSet( 14 | `{ field1 field2 { subFieldA subFieldB } }`, 15 | ); 16 | const result = pathsFromSelectionSet(selectionSet); 17 | expect(result).toEqual([ 18 | ['field1'], 19 | ['field2', 'subFieldA'], 20 | ['field2', 'subFieldB'], 21 | ]); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /packages/transports/common/src/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './types'; 2 | export * from './ObjMap'; 3 | export { executorFromSchema as createDefaultExecutor } from '@graphql-tools/executor'; 4 | export { getDocumentString } from '@envelop/core'; 5 | export { defaultPrintFn } from '@graphql-tools/executor-common'; 6 | export { abortSignalAny } from '@graphql-hive/signal'; 7 | -------------------------------------------------------------------------------- /packages/wrap/README.md: -------------------------------------------------------------------------------- 1 | Check API Reference for more information about this package; 2 | https://www.graphql-tools.com/docs/api/modules/wrap_src 3 | 4 | You can also learn more about Schema Wrapping in this chapter; 5 | https://www.graphql-tools.com/docs/schema-wrapping 6 | -------------------------------------------------------------------------------- /packages/wrap/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './wrapSchema.js'; 2 | export { 3 | defaultCreateProxyingResolver, 4 | generateProxyingResolvers, 5 | } from './generateProxyingResolvers.js'; 6 | 7 | export * from './transforms/index.js'; 8 | 9 | export * from './types.js'; 10 | export * from './introspect.js'; 11 | -------------------------------------------------------------------------------- /packages/wrap/src/transforms/PruneSchema.ts: -------------------------------------------------------------------------------- 1 | import { SubschemaConfig, Transform } from '@graphql-tools/delegate'; 2 | import { pruneSchema, PruneSchemaOptions } from '@graphql-tools/utils'; 3 | import { GraphQLSchema } from 'graphql'; 4 | 5 | interface PruneTypesTransformationContext extends Record {} 6 | 7 | export default class PruneTypes> 8 | implements Transform 9 | { 10 | private readonly options: PruneSchemaOptions; 11 | 12 | constructor(options: PruneSchemaOptions = {}) { 13 | this.options = options; 14 | } 15 | 16 | public transformSchema( 17 | originalWrappingSchema: GraphQLSchema, 18 | _subschemaConfig: SubschemaConfig, 19 | ): GraphQLSchema { 20 | return pruneSchema(originalWrappingSchema, this.options); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import tsconfigPaths from 'vite-tsconfig-paths'; 2 | import { defineConfig } from 'vitest/config'; 3 | 4 | // By default, Vite bypasses node_packages to native Node; meaning, imports to 5 | // packages that match the tsconfig paths wont work because Node will require the 6 | // packages as per the Node resolution spec. 7 | // 8 | // Vite will process inlined modules. 9 | const inline = [/@graphql-mesh\/.*/, /@omnigraph\/.*/]; 10 | 11 | export default defineConfig({ 12 | plugins: [tsconfigPaths()], 13 | test: { server: { deps: { inline } } }, 14 | resolve: { 15 | alias: { 16 | graphql: 'graphql/index.js', // TODO: why duplicate graphql errors when there's no multiple graphqls installed? mistery 17 | }, 18 | }, 19 | }); 20 | --------------------------------------------------------------------------------