diff --git a/.changeset/afraid-tomatoes-jam.md b/.changeset/afraid-tomatoes-jam.md new file mode 100644 index 000000000..4c60d2dbf --- /dev/null +++ b/.changeset/afraid-tomatoes-jam.md @@ -0,0 +1,5 @@ +--- +'@pothos/plugin-federation': minor +--- + +Add `linkUrl` option to buildSubGraphSchema diff --git a/packages/deno/packages/core/config-store.ts b/packages/deno/packages/core/config-store.ts index 896c2e2a5..bb55ec275 100644 --- a/packages/deno/packages/core/config-store.ts +++ b/packages/deno/packages/core/config-store.ts @@ -47,11 +47,11 @@ export default class ConfigStore { } addInterfaces(typeName: string, interfaces: InterfaceParam[] | (() => InterfaceParam[])) { if (typeof interfaces === "function" && this.pending) { - if (!this.pendingInterfaces.has(typeName)) { - this.pendingInterfaces.set(typeName, [interfaces]); + if (this.pendingInterfaces.has(typeName)) { + this.pendingInterfaces.get(typeName)!.push(interfaces); } else { - this.pendingInterfaces.get(typeName)!.push(interfaces); + this.pendingInterfaces.set(typeName, [interfaces]); } } else { diff --git a/packages/deno/packages/core/types/builder-options.ts b/packages/deno/packages/core/types/builder-options.ts index 0f8503a0f..886190cc6 100644 --- a/packages/deno/packages/core/types/builder-options.ts +++ b/packages/deno/packages/core/types/builder-options.ts @@ -70,7 +70,11 @@ export type ExposeNullability, ParentShape, Name extends keyof ParentShape> = FieldNullability & (Type extends [ unknown -] ? ParentShape[Name] extends readonly (infer T)[] | null | undefined ? T extends NonNullable ? ParentShape[Name] extends NonNullable ? boolean | { +] ? ParentShape[Name] extends readonly (infer T)[] | null | undefined ? [ + T +] extends [ + NonNullable +] ? ParentShape[Name] extends NonNullable ? boolean | { items: boolean; list: boolean; } : true | { diff --git a/packages/deno/packages/migration/mod.ts b/packages/deno/packages/migration/mod.ts new file mode 100644 index 000000000..e911f59d9 --- /dev/null +++ b/packages/deno/packages/migration/mod.ts @@ -0,0 +1,3 @@ +import Default from './index.ts'; +export * from './index.ts'; +export default Default; diff --git a/packages/deno/packages/plugin-add-graphql/mod.ts b/packages/deno/packages/plugin-add-graphql/mod.ts new file mode 100644 index 000000000..e911f59d9 --- /dev/null +++ b/packages/deno/packages/plugin-add-graphql/mod.ts @@ -0,0 +1,3 @@ +import Default from './index.ts'; +export * from './index.ts'; +export default Default; diff --git a/packages/deno/packages/plugin-directives/index.ts b/packages/deno/packages/plugin-directives/index.ts index 73d98ef0e..5bfeab2ad 100644 --- a/packages/deno/packages/plugin-directives/index.ts +++ b/packages/deno/packages/plugin-directives/index.ts @@ -24,7 +24,7 @@ export class PothosDirectivesPlugin extends BasePlugi } override onInputFieldConfig(fieldConfig: PothosInputFieldConfig) { const options = fieldConfig.pothosOptions; - if (!options.directives) { + if (!options.directives && !fieldConfig.extensions?.directives) { return fieldConfig; } return { @@ -37,7 +37,7 @@ export class PothosDirectivesPlugin extends BasePlugi } override onEnumValueConfig(valueConfig: PothosEnumValueConfig) { const options = valueConfig.pothosOptions; - if (!options.directives) { + if (!options.directives && !valueConfig.extensions?.directives) { return valueConfig; } return { @@ -50,7 +50,7 @@ export class PothosDirectivesPlugin extends BasePlugi } override onTypeConfig(typeConfig: PothosTypeConfig) { const options = typeConfig.pothosOptions; - if (!options.directives) { + if (!options.directives && !typeConfig.extensions?.directives) { return typeConfig; } return { diff --git a/packages/deno/packages/plugin-errors/index.ts b/packages/deno/packages/plugin-errors/index.ts index 4181a22f8..edab4b542 100644 --- a/packages/deno/packages/plugin-errors/index.ts +++ b/packages/deno/packages/plugin-errors/index.ts @@ -121,7 +121,7 @@ export class PothosErrorsPlugin extends BasePlugin typeName, - path: [{ type: resultName, name: dataFieldName }], + path: directResult ? [] : [{ type: resultName, name: dataFieldName }], }, }, }); @@ -140,7 +140,7 @@ export class PothosErrorsPlugin extends BasePlugin, fieldConfig: PothosOutputFieldConfig): GraphQLFieldResolver { - const pothosErrors = fieldConfig.extensions?.pothosErrors as typeof Error[] | undefined; + const pothosErrors = fieldConfig.extensions?.pothosErrors as (typeof Error)[] | undefined; if (!pothosErrors) { return resolver; } diff --git a/packages/plugin-federation/README.md b/packages/plugin-federation/README.md index babb6fed0..d1c3388d1 100644 --- a/packages/plugin-federation/README.md +++ b/packages/plugin-federation/README.md @@ -12,10 +12,11 @@ information on federation, see the ### Install -You will need to install the plugin, as well as `@apollo/subgraph` +You will need to install the plugin, as well as the directives plugin (`@pothos/plugin-directives`) +and `@apollo/subgraph` ```bash -yarn add @pothos/plugin-federation @apollo/subgraph +yarn add @pothos/plugin-federation @pothos/plugin-directives @apollo/subgraph ``` You will likely want to install @apollo/server as well, but it is not required if you want to use a @@ -28,10 +29,11 @@ yarn add @apollo/server ### Setup ```typescript +import DirectivePlugin from '@pothos/plugin-directives'; import FederationPlugin from '@pothos/plugin-federation'; const builder = new SchemaBuilder({ // If you are using other plugins, the federation plugin should be listed after plugins like auth that wrap resolvers - plugins: [FederationPlugin], + plugins: [DirectivePlugin, FederationPlugin], }); ``` @@ -162,7 +164,10 @@ ReviewType.implement({ ```typescript // Use new `toSubGraphSchema` method to add subGraph specific types and queries to the schema -const schema = builder.toSubGraphSchema({}); +const schema = builder.toSubGraphSchema({ + // defaults to v2.3 + linkUrl: 'https://specs.apollo.dev/federation/v2.3', +}); const server = new ApolloServer({ schema, @@ -179,3 +184,10 @@ startStandaloneServer(server, { listen: { port: 4000 } }) For a functional example that combines multiple graphs built with Pothos into a single schema see [https://github.com/hayes/pothos/tree/main/packages/plugin-federation/tests/example](https://github.com/hayes/pothos/tree/main/packages/plugin-federation/tests/example) + +### Printing the schema + +If you are printing the schema as a string for any reason, and then using the printed schema for +Apollo Federation(submitting if using Managed Federation, or composing manually with `rover`), you +must use `printSubgraphSchema`(from `@apollo/subgraph`) or another compatible way of printing the +schema(that includes directives) in order for it to work. diff --git a/packages/plugin-federation/src/global-types.ts b/packages/plugin-federation/src/global-types.ts index 54771aa6e..017166cb8 100644 --- a/packages/plugin-federation/src/global-types.ts +++ b/packages/plugin-federation/src/global-types.ts @@ -83,7 +83,11 @@ declare global { selection: (selection: SelectionFromShape) => Selection; - toSubGraphSchema: (options: BuildSchemaOptions) => GraphQLSchema; + toSubGraphSchema: ( + options: BuildSchemaOptions & { + linkUrl?: string; + }, + ) => GraphQLSchema; asEntity: , KeySelection extends Selection>( param: Param, diff --git a/packages/plugin-federation/src/schema-builder.ts b/packages/plugin-federation/src/schema-builder.ts index 7a02a12a2..8aa4331c7 100644 --- a/packages/plugin-federation/src/schema-builder.ts +++ b/packages/plugin-federation/src/schema-builder.ts @@ -46,7 +46,10 @@ schemaBuilderProto.externalRef = function externalRef< return new ExternalEntityRef(this, name, key, resolveReference); }; -schemaBuilderProto.toSubGraphSchema = function toSubGraphSchema(options) { +schemaBuilderProto.toSubGraphSchema = function toSubGraphSchema({ + linkUrl = 'https://specs.apollo.dev/federation/v2.3', + ...options +}) { const schema = this.toSchema({ ...options, extensions: { diff --git a/website/pages/docs/plugins/federation.mdx b/website/pages/docs/plugins/federation.mdx index 56fef26dc..bbd819a54 100644 --- a/website/pages/docs/plugins/federation.mdx +++ b/website/pages/docs/plugins/federation.mdx @@ -178,7 +178,10 @@ ReviewType.implement({ ```typescript // Use new `toSubGraphSchema` method to add subGraph specific types and queries to the schema -const schema = builder.toSubGraphSchema({}); +const schema = builder.toSubGraphSchema({ + // defaults to v2.3 + linkUrl: 'https://specs.apollo.dev/federation/v2.3', +}); const server = new ApolloServer({ schema,