Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
5fc73a3
feat: implement handling and validation for fields with arguments
Noroth Sep 5, 2025
19b2ded
chore: format code
Noroth Sep 22, 2025
62d8542
feat: add support for field resolvers in protographic
Noroth Oct 16, 2025
0ab9b8a
add field resolvers to the demo
Noroth Oct 21, 2025
6d68c30
feat: initial support for field resolvers
Noroth Oct 21, 2025
47a6c0f
chore: update composition-go
Noroth Oct 21, 2025
c7f8524
chore: add export
Noroth Oct 21, 2025
d867ec1
chore: use extension in import
Noroth Oct 21, 2025
91bb1b3
chore: regenerate test configs
Noroth Oct 21, 2025
2682575
implement directivesRoot for requireFetchReasons
ysmolski Oct 22, 2025
e1e3c4b
chore: update directive name
Noroth Oct 22, 2025
c41534e
chore: update go mod for test
Noroth Oct 24, 2025
11d0f3d
chore: fallback to empty list
Noroth Oct 27, 2025
9c6d19a
chore: update test configs
Noroth Oct 27, 2025
4cafba1
chore: handle snake_case for context fields
Noroth Oct 27, 2025
b6081e4
chore: update SDL rules
Noroth Oct 27, 2025
16234ed
chore: include protographic in router ci
Noroth Oct 27, 2025
a5f7fc5
Merge branch 'main' of github.com:wundergraph/cosmo into ludwig/eng-6…
Noroth Oct 27, 2025
1f3fdbf
chore: update composition
Noroth Oct 27, 2025
a92ba67
use temporary go-tools version
Noroth Oct 27, 2025
c43b00f
chore: update docstrings
Noroth Oct 27, 2025
986381e
chore: more improvements
Noroth Oct 27, 2025
cb3f863
chore: improvements
Noroth Oct 27, 2025
9e50102
chore: clean up
Aenimus Oct 30, 2025
7a19f53
chore: use temporary commit
Noroth Oct 30, 2025
d3606c8
chore: detect nested cycle in references
Noroth Oct 30, 2025
7c88361
chore: lint mimimi
Noroth Oct 30, 2025
ccffcc9
chore: remove protographic again
Noroth Oct 30, 2025
261bcd7
chore: use proper naming
Noroth Oct 30, 2025
c320f6b
chore: update composition-go
Noroth Oct 30, 2025
ab7c5d4
chore: remove unused import
Noroth Oct 31, 2025
c3efe8f
chore: skip directive with config
Noroth Oct 31, 2025
8e2793b
Merge branch 'main' of github.com:wundergraph/cosmo into ludwig/eng-6…
Noroth Oct 31, 2025
3eaf12f
chore: temporary engine version
Noroth Oct 31, 2025
754c4e6
chore: use values
Noroth Nov 3, 2025
b9fc1dd
chore: remove anonymous function
Noroth Nov 3, 2025
3821ecb
chore: simplify
Noroth Nov 3, 2025
d770ea8
chore: improve loop
Noroth Nov 3, 2025
491bb26
Merge branch 'main' into ludwig/eng-6993-implement-field-resolver-for…
Noroth Nov 10, 2025
9ff5af9
chore: update engine version
Noroth Nov 10, 2025
de5639e
Merge branch 'main' into ludwig/eng-6993-implement-field-resolver-for…
Noroth Nov 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
338 changes: 169 additions & 169 deletions composition-go/index.global.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions composition/src/utils/string-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export const CONFIGURE_DESCRIPTION = 'openfed__configureDescription';
export const CONFIGURE_CHILD_DESCRIPTIONS = 'openfed__configureChildDescriptions';
export const CONSUMER_INACTIVE_THRESHOLD = 'consumerInactiveThreshold';
export const CONSUMER_NAME = 'consumerName';
export const CONNECT_FIELD_RESOLVER = 'connect__fieldResolver';
export const CONTEXT = 'context';
export const DEFAULT = 'default';
export const DEFAULT_EDFS_PROVIDER_ID = 'default';
export const DEFAULT_MUTATION = 'Mutation';
Expand Down
3 changes: 3 additions & 0 deletions composition/src/v1/constants/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
COMPOSE_DIRECTIVE,
CONFIGURE_CHILD_DESCRIPTIONS,
CONFIGURE_DESCRIPTION,
CONNECT_FIELD_RESOLVER,
DEPRECATED,
EDFS_KAFKA_PUBLISH,
EDFS_KAFKA_SUBSCRIBE,
Expand Down Expand Up @@ -43,6 +44,7 @@ import {
COMPOSE_DIRECTIVE_DEFINITION,
CONFIGURE_CHILD_DESCRIPTIONS_DEFINITION,
CONFIGURE_DESCRIPTION_DEFINITION,
CONNECT_FIELD_RESOLVER_DEFINITION,
DEPRECATED_DEFINITION,
EDFS_KAFKA_PUBLISH_DEFINITION,
EDFS_KAFKA_SUBSCRIBE_DEFINITION,
Expand Down Expand Up @@ -78,6 +80,7 @@ export const DIRECTIVE_DEFINITION_BY_NAME: ReadonlyMap<DirectiveName, DirectiveD
[COMPOSE_DIRECTIVE, COMPOSE_DIRECTIVE_DEFINITION],
[CONFIGURE_DESCRIPTION, CONFIGURE_DESCRIPTION_DEFINITION],
[CONFIGURE_CHILD_DESCRIPTIONS, CONFIGURE_CHILD_DESCRIPTIONS_DEFINITION],
[CONNECT_FIELD_RESOLVER, CONNECT_FIELD_RESOLVER_DEFINITION],
[DEPRECATED, DEPRECATED_DEFINITION],
[EDFS_KAFKA_PUBLISH, EDFS_KAFKA_PUBLISH_DEFINITION],
[EDFS_KAFKA_SUBSCRIBE, EDFS_KAFKA_SUBSCRIBE_DEFINITION],
Expand Down
18 changes: 17 additions & 1 deletion composition/src/v1/constants/directive-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
CONDITION,
CONFIGURE_CHILD_DESCRIPTIONS,
CONFIGURE_DESCRIPTION,
CONNECT_FIELD_RESOLVER,
CONTEXT,
DEFAULT_EDFS_PROVIDER_ID,
DEPRECATED,
DESCRIPTION_OVERRIDE,
Expand All @@ -30,7 +32,6 @@ import {
EXTENDS,
EXTERNAL,
FIELD_DEFINITION_UPPER,
FIELD_SET_SCALAR,
FIELDS,
FOR,
FROM,
Expand Down Expand Up @@ -184,6 +185,21 @@ export const CONFIGURE_DESCRIPTION_DEFINITION: DirectiveDefinitionNode = {
repeatable: false,
};

// directive @connect__fieldResolver(context: openfed__FieldSet!) on FIELD_DEFINITION
export const CONNECT_FIELD_RESOLVER_DEFINITION: DirectiveDefinitionNode = {
arguments: [
{
kind: Kind.INPUT_VALUE_DEFINITION,
name: stringToNameNode(CONTEXT),
type: REQUIRED_FIELDSET_TYPE_NODE,
},
],
kind: Kind.DIRECTIVE_DEFINITION,
locations: stringArrayToNameNodeArray([FIELD_DEFINITION_UPPER]),
name: stringToNameNode(CONNECT_FIELD_RESOLVER),
repeatable: false,
};

export const DEPRECATED_DEFINITION: DirectiveDefinitionNode = {
arguments: [
{
Expand Down
2 changes: 2 additions & 0 deletions composition/src/v1/constants/strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
AND_UPPER,
ARGUMENT_DEFINITION_UPPER,
BOOLEAN_SCALAR,
CONNECT_FIELD_RESOLVER,
CONSUMER_INACTIVE_THRESHOLD,
CONSUMER_NAME,
DEPRECATED,
Expand Down Expand Up @@ -108,6 +109,7 @@ export const DEPENDENCIES_BY_DIRECTIVE_NAME: ReadonlyMap<DirectiveName, Array<De
DirectiveName,
Array<DefinitionNode>
>([
[CONNECT_FIELD_RESOLVER, [FIELD_SET_SCALAR_DEFINITION]],
[EDFS_NATS_SUBSCRIBE, [EDFS_NATS_STREAM_CONFIGURATION_DEFINITION]],
[KEY, [FIELD_SET_SCALAR_DEFINITION]],
[LINK, [LINK_IMPORT_DEFINITION, LINK_PURPOSE_DEFINITION]],
Expand Down
21 changes: 21 additions & 0 deletions composition/src/v1/normalization/directive-definition-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
CONDITION,
CONFIGURE_CHILD_DESCRIPTIONS,
CONFIGURE_DESCRIPTION,
CONNECT_FIELD_RESOLVER,
CONTEXT,
DEFAULT_EDFS_PROVIDER_ID,
DEPRECATED,
DESCRIPTION_OVERRIDE,
Expand Down Expand Up @@ -79,6 +81,7 @@ import {
COMPOSE_DIRECTIVE_DEFINITION,
CONFIGURE_CHILD_DESCRIPTIONS_DEFINITION,
CONFIGURE_DESCRIPTION_DEFINITION,
CONNECT_FIELD_RESOLVER_DEFINITION,
DEPRECATED_DEFINITION,
EDFS_KAFKA_PUBLISH_DEFINITION,
EDFS_KAFKA_SUBSCRIBE_DEFINITION,
Expand Down Expand Up @@ -206,6 +209,24 @@ export const CONFIGURE_CHILD_DESCRIPTIONS_DEFINITION_DATA: DirectiveDefinitionDa
requiredArgumentNames: new Set<string>(),
};

export const CONNECT_FIELD_RESOLVER_DEFINITION_DATA: DirectiveDefinitionData = {
argumentTypeNodeByName: new Map<string, ArgumentData>([
[
CONTEXT,
{
name: CONTEXT,
typeNode: REQUIRED_FIELDSET_TYPE_NODE,
},
],
]),
isRepeatable: false,
locations: new Set<string>([FIELD_DEFINITION_UPPER]),
name: CONNECT_FIELD_RESOLVER,
node: CONNECT_FIELD_RESOLVER_DEFINITION,
optionalArgumentNames: new Set<string>(),
requiredArgumentNames: new Set<string>([CONTEXT]),
};

export const DEPRECATED_DEFINITION_DATA: DirectiveDefinitionData = {
argumentTypeNodeByName: new Map<string, ArgumentData>([
[
Expand Down
3 changes: 3 additions & 0 deletions composition/src/v1/normalization/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
COMPOSE_DIRECTIVE_DEFINITION_DATA,
CONFIGURE_CHILD_DESCRIPTIONS_DEFINITION_DATA,
CONFIGURE_DESCRIPTION_DEFINITION_DATA,
CONNECT_FIELD_RESOLVER_DEFINITION_DATA,
DEPRECATED_DEFINITION_DATA,
EXTENDS_DEFINITION_DATA,
EXTERNAL_DEFINITION_DATA,
Expand Down Expand Up @@ -56,6 +57,7 @@ import {
COMPOSE_DIRECTIVE,
CONFIGURE_CHILD_DESCRIPTIONS,
CONFIGURE_DESCRIPTION,
CONNECT_FIELD_RESOLVER,
DEPRECATED,
EDFS_KAFKA_PUBLISH,
EDFS_KAFKA_SUBSCRIBE,
Expand Down Expand Up @@ -394,6 +396,7 @@ export function initializeDirectiveDefinitionDatas(): Map<string, DirectiveDefin
[COMPOSE_DIRECTIVE, COMPOSE_DIRECTIVE_DEFINITION_DATA],
[CONFIGURE_DESCRIPTION, CONFIGURE_DESCRIPTION_DEFINITION_DATA],
[CONFIGURE_CHILD_DESCRIPTIONS, CONFIGURE_CHILD_DESCRIPTIONS_DEFINITION_DATA],
[CONNECT_FIELD_RESOLVER, CONNECT_FIELD_RESOLVER_DEFINITION_DATA],
[DEPRECATED, DEPRECATED_DEFINITION_DATA],
[EDFS_KAFKA_PUBLISH, KAFKA_PUBLISH_DEFINITION_DATA],
[EDFS_KAFKA_SUBSCRIBE, KAFKA_SUBSCRIBE_DEFINITION_DATA],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { describe, expect, test } from 'vitest';
import {
CONNECT_FIELD_RESOLVER,
CONTEXT,
invalidDirectiveError,
NormalizationFailure,
NormalizationSuccess,
normalizeSubgraph,
ROUTER_COMPATIBILITY_VERSION_ONE,
Subgraph,
undefinedRequiredArgumentsErrorMessage,
} from '../../../src';
import { parse, printSchema } from 'graphql';
import {
normalizeString,
normalizeSubgraphFailure,
normalizeSubgraphSuccess,
schemaToSortedNormalizedString,
} from '../../utils/utils';
import { CONNECT_FIELD_RESOLVER_DIRECTIVE, OPENFED_FIELD_SET, SCHEMA_QUERY_DEFINITION } from '../utils/utils';

describe('@connect__fieldResolver tests', () => {
test('that @connect__fieldResolver is automatically included in the subgraph schema if it is referenced', () => {
const { schema, warnings } = normalizeSubgraphSuccess(
subgraphWithConnectConfigureResolver,
ROUTER_COMPATIBILITY_VERSION_ONE,
);
expect(warnings).toHaveLength(0);
expect(schemaToSortedNormalizedString(schema)).toBe(
normalizeString(
SCHEMA_QUERY_DEFINITION +
CONNECT_FIELD_RESOLVER_DIRECTIVE +
`
type Foo {
bar(baz: String!): String @connect__fieldResolver(context: "id")
id: ID!
}

type Query {
foo: Foo!
}
` +
OPENFED_FIELD_SET,
),
);
});

test('that @connect__fieldResolver needs to have a context', () => {
const { errors } = normalizeSubgraphFailure(
subgraphWithConnectConfigureResolverWithoutContext,
ROUTER_COMPATIBILITY_VERSION_ONE,
);

expect(errors).toHaveLength(1);
expect(errors[0]).toStrictEqual(
invalidDirectiveError(CONNECT_FIELD_RESOLVER, `Foo.bar`, `1st`, [
undefinedRequiredArgumentsErrorMessage(CONNECT_FIELD_RESOLVER, [CONTEXT], []),
]),
);
});
});

const subgraphWithConnectConfigureResolver: Subgraph = {
name: 'connect-configure-resolver',
url: '',
definitions: parse(`
type Foo {
bar(baz: String!): String @connect__fieldResolver(context: "id")
id: ID!
}

type Query {
foo: Foo!
}
`),
};

const subgraphWithConnectConfigureResolverWithoutContext: Subgraph = {
name: 'connect-configure-resolver-without-context',
url: '',
definitions: parse(`
type Foo {
bar(baz: String!): String @connect__fieldResolver
id: ID!
}
`),
};
4 changes: 4 additions & 0 deletions composition/tests/v1/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export const CONFIGURE_DESCRIPTION_DIRECTIVE = `
directive @openfed__configureDescription(descriptionOverride: String, propagate: Boolean! = true) on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | SCHEMA | UNION
`;

export const CONNECT_FIELD_RESOLVER_DIRECTIVE = `
directive @connect__fieldResolver(context: openfed__FieldSet!) on FIELD_DEFINITION
`;

export const EDFS_NATS_PUBLISH_DIRECTIVE = `
directive @edfs__natsPublish(providerId: String! = "default", subject: String!) on FIELD_DEFINITION
`;
Expand Down
Loading
Loading