diff --git a/codegen.mts b/codegen.mts index ae23bb9ff..93196c66f 100644 --- a/codegen.mts +++ b/codegen.mts @@ -12,7 +12,10 @@ const config: CodegenConfig = { typeDefsFilePath: false, mergeSchema: { path: '../../../../schema.graphql', - config: { includeDirectives: true }, + config: { + includeDirectives: true, + append: '\n\n directive @oneOf on INPUT_OBJECT', + }, }, resolverGeneration: 'minimal', resolverMainFileMode: 'modules', diff --git a/deployment/utils/publish-graphql-schema.ts b/deployment/utils/publish-graphql-schema.ts index c942d12f6..ac7d51b1d 100644 --- a/deployment/utils/publish-graphql-schema.ts +++ b/deployment/utils/publish-graphql-schema.ts @@ -15,7 +15,7 @@ export function publishGraphQLSchema(args: { }) { const command = (accessToken: string) => `schema:publish` + - ` --registry.endpoint ${args.registry.endpoint} --registry.accessToken ${accessToken} --target ${args.registry.target}` + + ` --registry.endpoint ${args.registry.endpoint} --registry.accessToken ${accessToken} --target ${args.registry.target} --service graphql` + ` --commit ${args.version.commit} --author "Hive CD" ./schema.graphqls`; return new local.Command( diff --git a/package.json b/package.json index fa8a50eb1..1536b5c1f 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,8 @@ "p-cancelable@4.0.1": "patches/p-cancelable@4.0.1.patch", "bentocache": "patches/bentocache.patch", "nextra": "patches/nextra.patch", - "nextra-theme-docs": "patches/nextra-theme-docs.patch" + "nextra-theme-docs": "patches/nextra-theme-docs.patch", + "@graphql-codegen/schema-ast": "patches/@graphql-codegen__schema-ast.patch" } } } diff --git a/packages/services/api/src/modules/shared/module.graphql.ts b/packages/services/api/src/modules/shared/module.graphql.ts index 739634841..cf0b5fb62 100644 --- a/packages/services/api/src/modules/shared/module.graphql.ts +++ b/packages/services/api/src/modules/shared/module.graphql.ts @@ -21,7 +21,7 @@ export default gql` extend schema @link(url: "https://specs.apollo.dev/link/v1.0") - @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@tag", "@composeDirective"]) + @link(url: "https://specs.apollo.dev/federation/v2.9", import: ["@tag", "@composeDirective"]) @link(url: "https://github.com/graphql/graphql-spec/pull/825/v0.1", import: ["@oneOf"]) @composeDirective(name: "@oneOf") @@ -32,7 +32,7 @@ export default gql` directive @tag( name: String! - ) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION | SCHEMA + ) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION type Query { _: Boolean @tag(name: "public") @@ -42,6 +42,10 @@ export default gql` _: Boolean @tag(name: "public") } + type Subscription { + _: Boolean @tag(name: "public") + } + type PageInfo { hasNextPage: Boolean! @tag(name: "public") hasPreviousPage: Boolean! @tag(name: "public") diff --git a/packages/services/api/src/modules/shared/resolvers/Subscription/_.ts b/packages/services/api/src/modules/shared/resolvers/Subscription/_.ts new file mode 100644 index 000000000..c00064c41 --- /dev/null +++ b/packages/services/api/src/modules/shared/resolvers/Subscription/_.ts @@ -0,0 +1,8 @@ +import type { SubscriptionResolvers } from './../../../../__generated__/types'; + +export const _: NonNullable = { + // eslint-disable-next-line require-yield + async *subscribe() { + return; + }, +}; diff --git a/packages/services/server/src/public-graphql-schema.ts b/packages/services/server/src/public-graphql-schema.ts index 8ad6d540f..ff3b3b536 100644 --- a/packages/services/server/src/public-graphql-schema.ts +++ b/packages/services/server/src/public-graphql-schema.ts @@ -1,33 +1,19 @@ -import { Kind, OperationTypeNode, parse, type DocumentNode } from 'graphql'; +import { parse, type DocumentNode } from 'graphql'; import { createSchema } from 'graphql-yoga'; import { mergeTypeDefs } from '@graphql-tools/merge'; import { type Registry } from '@hive/api'; import { composeFederationV2 } from '@hive/schema/src/lib/compose'; import { applyTagFilterOnSubgraphs } from '@hive/schema/src/lib/federation-tag-extraction'; -type Writeable = { -readonly [P in keyof T]: T[P] }; - /** * Creates the public GraphQL schema from the private GraphQL Schema Registry definition. */ export function createPublicGraphQLSchema(registry: Registry) { // Merge all modules type definitions into a single document node while excluding the `Subscription` type (for now) const documentNode: DocumentNode = mergeTypeDefs(registry.typeDefs, { - // For now we exclude the subscription type - exclusions: ['Subscription'], throwOnConflict: true, }); - // We still have to remove the `Subscription` type from the [`schema`](https://spec.graphql.org/draft/#sec-Schema) - for (const definition of documentNode.definitions) { - if (definition.kind === Kind.SCHEMA_EXTENSION || definition.kind === Kind.SCHEMA_DEFINITION) { - (definition as Writeable).operationTypes = - definition.operationTypes?.filter( - ttype => ttype.operation !== OperationTypeNode.SUBSCRIPTION, - ); - } - } - // Use our tag filter logic for marking everything not tagged with `@tag(name: "public")` as @inaccessible const [filteredSubgraph] = applyTagFilterOnSubgraphs( [ diff --git a/patches/@graphql-codegen__schema-ast.patch b/patches/@graphql-codegen__schema-ast.patch new file mode 100644 index 000000000..f94073ef2 --- /dev/null +++ b/patches/@graphql-codegen__schema-ast.patch @@ -0,0 +1,66 @@ +diff --git a/cjs/index.js b/cjs/index.js +index ed643f4440f514b0d933fea2d41d3fa456f99bd4..bcea9c4a71463bd46d20837a62d8b6d490b66c88 100644 +--- a/cjs/index.js ++++ b/cjs/index.js +@@ -4,13 +4,14 @@ exports.transformSchemaAST = exports.validate = exports.plugin = void 0; + const path_1 = require("path"); + const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers"); + const graphql_1 = require("graphql"); +-const plugin = async (schema, _documents, { commentDescriptions = false, includeDirectives = false, includeIntrospectionTypes = false, sort = false, federation, }) => { ++const plugin = async (schema, _documents, { commentDescriptions = false, includeDirectives = false, includeIntrospectionTypes = false, sort = false, federation, append = '' }) => { + const transformedSchemaAndAst = transformSchemaAST(schema, { sort, federation, includeIntrospectionTypes }); + return [ + includeIntrospectionTypes ? (0, graphql_1.printIntrospectionSchema)(transformedSchemaAndAst.schema) : null, + includeDirectives + ? (0, graphql_1.print)(transformedSchemaAndAst.ast) + : graphql_1.printSchema(transformedSchemaAndAst.schema, { commentDescriptions }), ++ append, + ] + .filter(Boolean) + .join('\n'); +diff --git a/esm/index.js b/esm/index.js +index f386116b7c1931f84b7364ac6fcf743ccecafc5a..2d7e12c89722607ac62d64cd8fbbb5f3b332b297 100644 +--- a/esm/index.js ++++ b/esm/index.js +@@ -1,13 +1,14 @@ + import { extname } from 'path'; + import { getCachedDocumentNodeFromSchema, removeFederation, } from '@graphql-codegen/plugin-helpers'; + import { buildASTSchema, extendSchema, parse, print, printIntrospectionSchema, printSchema, visit, } from 'graphql'; +-export const plugin = async (schema, _documents, { commentDescriptions = false, includeDirectives = false, includeIntrospectionTypes = false, sort = false, federation, }) => { ++export const plugin = async (schema, _documents, { commentDescriptions = false, includeDirectives = false, includeIntrospectionTypes = false, sort = false, federation, append = '' }) => { + const transformedSchemaAndAst = transformSchemaAST(schema, { sort, federation, includeIntrospectionTypes }); + return [ + includeIntrospectionTypes ? printIntrospectionSchema(transformedSchemaAndAst.schema) : null, + includeDirectives + ? print(transformedSchemaAndAst.ast) + : printSchema(transformedSchemaAndAst.schema, { commentDescriptions }), ++ append, + ] + .filter(Boolean) + .join('\n'); +diff --git a/typings/index.d.cts b/typings/index.d.cts +index f2df25dbcbc5c7c0d0764452e06511dff8a1e896..083980b957de8b94ca9f77b801fcee34ef4189af 100644 +--- a/typings/index.d.cts ++++ b/typings/index.d.cts +@@ -27,6 +27,8 @@ export interface SchemaASTConfig { + * ``` + */ + includeDirectives?: boolean; ++ /** Text to be appended at the end of the generated output. */ ++ append?: string; + /** + * @description Include introspection types to Schema output. + * @default false +diff --git a/typings/index.d.ts b/typings/index.d.ts +index f2df25dbcbc5c7c0d0764452e06511dff8a1e896..083980b957de8b94ca9f77b801fcee34ef4189af 100644 +--- a/typings/index.d.ts ++++ b/typings/index.d.ts +@@ -27,6 +27,8 @@ export interface SchemaASTConfig { + * ``` + */ + includeDirectives?: boolean; ++ /** Text to be appended at the end of the generated output. */ ++ append?: string; + /** + * @description Include introspection types to Schema output. + * @default false diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2a7a4e2be..903ea4854 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ patchedDependencies: '@graphiql/react': hash: 1018befc9149cbc43bc2bf8982d52090a580e68df34b46674234f4e58eb6d0a0 path: patches/@graphiql__react.patch + '@graphql-codegen/schema-ast': + hash: 2280c6d4f2e9268fc118d06dc95deea7e9b58200010db1b332004627d6793a9f + path: patches/@graphql-codegen__schema-ast.patch '@graphql-eslint/eslint-plugin@3.20.1': hash: 695fba67df25ba9d46472c8398c94c6a2ccf75d902321d8f95150f68e940313e path: patches/@graphql-eslint__eslint-plugin@3.20.1.patch @@ -17889,7 +17892,7 @@ snapshots: '@eddeee888/gcg-server-config': 0.2.2(encoding@0.1.13)(graphql@16.9.0) '@graphql-codegen/add': 5.0.3(graphql@16.9.0) '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.9.0) - '@graphql-codegen/schema-ast': 4.1.0(graphql@16.9.0) + '@graphql-codegen/schema-ast': 4.1.0(patch_hash=2280c6d4f2e9268fc118d06dc95deea7e9b58200010db1b332004627d6793a9f)(graphql@16.9.0) '@graphql-codegen/typescript': 4.1.5(encoding@0.1.13)(graphql@16.9.0) '@graphql-codegen/typescript-resolvers': 4.4.4(encoding@0.1.13)(graphql@16.9.0) '@graphql-tools/merge': 9.0.24(graphql@16.9.0) @@ -18530,7 +18533,7 @@ snapshots: lodash: 4.17.21 tslib: 2.6.3 - '@graphql-codegen/schema-ast@4.1.0(graphql@16.9.0)': + '@graphql-codegen/schema-ast@4.1.0(patch_hash=2280c6d4f2e9268fc118d06dc95deea7e9b58200010db1b332004627d6793a9f)(graphql@16.9.0)': dependencies: '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.9.0) '@graphql-tools/utils': 10.8.6(graphql@16.9.0) @@ -18577,7 +18580,7 @@ snapshots: '@graphql-codegen/typescript@4.1.5(encoding@0.1.13)(graphql@16.9.0)': dependencies: '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.9.0) - '@graphql-codegen/schema-ast': 4.1.0(graphql@16.9.0) + '@graphql-codegen/schema-ast': 4.1.0(patch_hash=2280c6d4f2e9268fc118d06dc95deea7e9b58200010db1b332004627d6793a9f)(graphql@16.9.0) '@graphql-codegen/visitor-plugin-common': 5.7.1(encoding@0.1.13)(graphql@16.9.0) auto-bind: 4.0.0 graphql: 16.9.0