@apollo/federation-internals 2.1.0-alpha.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -4
- package/dist/buildSchema.d.ts.map +1 -1
- package/dist/buildSchema.js +14 -4
- package/dist/buildSchema.js.map +1 -1
- package/dist/coreSpec.d.ts +1 -4
- package/dist/coreSpec.d.ts.map +1 -1
- package/dist/coreSpec.js +1 -5
- package/dist/coreSpec.js.map +1 -1
- package/dist/definitions.d.ts +66 -34
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +309 -165
- package/dist/definitions.js.map +1 -1
- package/dist/error.d.ts +5 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +47 -1
- package/dist/error.js.map +1 -1
- package/dist/extractSubgraphsFromSupergraph.d.ts.map +1 -1
- package/dist/extractSubgraphsFromSupergraph.js +135 -5
- package/dist/extractSubgraphsFromSupergraph.js.map +1 -1
- package/dist/federation.d.ts +3 -2
- package/dist/federation.d.ts.map +1 -1
- package/dist/federation.js +12 -7
- package/dist/federation.js.map +1 -1
- package/dist/inaccessibleSpec.js +1 -2
- package/dist/inaccessibleSpec.js.map +1 -1
- package/dist/operations.d.ts +44 -20
- package/dist/operations.d.ts.map +1 -1
- package/dist/operations.js +287 -27
- package/dist/operations.js.map +1 -1
- package/dist/print.d.ts +1 -1
- package/dist/print.d.ts.map +1 -1
- package/dist/print.js +1 -1
- package/dist/print.js.map +1 -1
- package/dist/schemaUpgrader.d.ts.map +1 -1
- package/dist/schemaUpgrader.js +6 -6
- package/dist/schemaUpgrader.js.map +1 -1
- package/dist/supergraphs.d.ts +1 -3
- package/dist/supergraphs.d.ts.map +1 -1
- package/dist/supergraphs.js +9 -22
- package/dist/supergraphs.js.map +1 -1
- package/dist/utils.d.ts +10 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +40 -1
- package/dist/utils.js.map +1 -1
- package/package.json +3 -4
- package/src/__tests__/coreSpec.test.ts +1 -1
- package/src/__tests__/definitions.test.ts +27 -0
- package/src/__tests__/extractSubgraphsFromSupergraph.test.ts +9 -5
- package/src/__tests__/operations.test.ts +36 -0
- package/src/__tests__/removeInaccessibleElements.test.ts +1 -3
- package/src/__tests__/schemaUpgrader.test.ts +0 -1
- package/src/__tests__/subgraphValidation.test.ts +1 -2
- package/src/buildSchema.ts +20 -7
- package/src/coreSpec.ts +2 -7
- package/src/definitions.ts +355 -155
- package/src/error.ts +62 -0
- package/src/extractSubgraphsFromSupergraph.ts +198 -7
- package/src/federation.ts +11 -4
- package/src/inaccessibleSpec.ts +2 -5
- package/src/operations.ts +428 -40
- package/src/print.ts +3 -3
- package/src/schemaUpgrader.ts +7 -6
- package/src/supergraphs.ts +16 -25
- package/src/utils.ts +49 -0
- package/tsconfig.test.tsbuildinfo +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
+
defaultRootName,
|
|
2
3
|
Schema,
|
|
4
|
+
SchemaRootKind,
|
|
3
5
|
} from '../../dist/definitions';
|
|
4
6
|
import { buildSchema } from '../../dist/buildSchema';
|
|
5
7
|
import { Field, FieldSelection, parseOperation, SelectionSet } from '../../dist/operations';
|
|
6
8
|
import './matchers';
|
|
9
|
+
import { GraphQLError } from 'graphql';
|
|
7
10
|
|
|
8
11
|
function parseSchema(schema: string): Schema {
|
|
9
12
|
try {
|
|
@@ -341,3 +344,36 @@ describe('selection set freezing', () => {
|
|
|
341
344
|
expect(s2.toString()).toBe('{ t { b } }');
|
|
342
345
|
});
|
|
343
346
|
});
|
|
347
|
+
|
|
348
|
+
describe('validations', () => {
|
|
349
|
+
test.each([
|
|
350
|
+
{ directive: '@defer', rootKind: 'mutation' },
|
|
351
|
+
{ directive: '@defer', rootKind: 'subscription' },
|
|
352
|
+
{ directive: '@stream', rootKind: 'mutation' },
|
|
353
|
+
{ directive: '@stream', rootKind: 'subscription' },
|
|
354
|
+
])('reject $directive on $rootKind type', ({ directive, rootKind }) => {
|
|
355
|
+
const schema = parseSchema(`
|
|
356
|
+
type Query {
|
|
357
|
+
x: String
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
type Mutation {
|
|
361
|
+
x: String
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
type Subscription {
|
|
365
|
+
x: String
|
|
366
|
+
}
|
|
367
|
+
`);
|
|
368
|
+
|
|
369
|
+
expect(() => {
|
|
370
|
+
parseOperation(schema, `
|
|
371
|
+
${rootKind} {
|
|
372
|
+
... ${directive} {
|
|
373
|
+
x
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
`)
|
|
377
|
+
}).toThrowError(new GraphQLError(`The @defer and @stream directives cannot be used on ${rootKind} root type "${defaultRootName(rootKind as SchemaRootKind)}"`));
|
|
378
|
+
});
|
|
379
|
+
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ArgumentDefinition,
|
|
3
|
-
errorCauses,
|
|
4
3
|
FieldDefinition,
|
|
5
4
|
InterfaceType,
|
|
6
5
|
ObjectType,
|
|
@@ -8,8 +7,8 @@ import {
|
|
|
8
7
|
} from "../definitions";
|
|
9
8
|
import { buildSchema } from "../buildSchema";
|
|
10
9
|
import { removeInaccessibleElements } from "../inaccessibleSpec";
|
|
11
|
-
import { GraphQLErrorExt } from "@apollo/core-schema/dist/error";
|
|
12
10
|
import { GraphQLError } from "graphql";
|
|
11
|
+
import { errorCauses } from "../error";
|
|
13
12
|
|
|
14
13
|
describe("removeInaccessibleElements", () => {
|
|
15
14
|
const INACCESSIBLE_V02_HEADER = `
|
|
@@ -31,7 +30,6 @@ describe("removeInaccessibleElements", () => {
|
|
|
31
30
|
`;
|
|
32
31
|
|
|
33
32
|
function getCauses(e: unknown): GraphQLError[] {
|
|
34
|
-
expect(e instanceof GraphQLErrorExt).toBeTruthy();
|
|
35
33
|
const causes = errorCauses(e as Error);
|
|
36
34
|
expect(causes).toBeDefined();
|
|
37
35
|
expect(Array.isArray(causes)).toBeTruthy();
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { DocumentNode } from 'graphql';
|
|
2
2
|
import gql from 'graphql-tag';
|
|
3
|
-
import { Subgraph } from '..';
|
|
4
|
-
import { errorCauses } from '../definitions';
|
|
3
|
+
import { Subgraph, errorCauses } from '..';
|
|
5
4
|
import { asFed2SubgraphDocument, buildSubgraph } from "../federation"
|
|
6
5
|
import { defaultPrintOptions, printSchema } from '../print';
|
|
7
6
|
import './matchers';
|
package/src/buildSchema.ts
CHANGED
|
@@ -52,10 +52,9 @@ import {
|
|
|
52
52
|
EnumType,
|
|
53
53
|
Extension,
|
|
54
54
|
ErrGraphQLValidationFailed,
|
|
55
|
-
errorCauses,
|
|
56
55
|
NamedSchemaElement,
|
|
57
56
|
} from "./definitions";
|
|
58
|
-
import { ERRORS, withModifiedErrorNodes } from "./error";
|
|
57
|
+
import { ERRORS, errorCauses, withModifiedErrorNodes } from "./error";
|
|
59
58
|
|
|
60
59
|
function buildValue(value?: ValueNode): any {
|
|
61
60
|
return value ? valueFromASTUntyped(value) : undefined;
|
|
@@ -100,7 +99,7 @@ export function buildSchemaFromAST(
|
|
|
100
99
|
// is that:
|
|
101
100
|
// 1. we can (enum values are self-contained and cannot reference anything that may need to be imported first; this
|
|
102
101
|
// is also why we skip directive applications at that point, as those _may_ reference something that hasn't been imported yet)
|
|
103
|
-
// 2. this allows the code to handle better the case where the `link__Purpose` enum is provided in the AST despite the `@link`
|
|
102
|
+
// 2. this allows the code to handle better the case where the `link__Purpose` enum is provided in the AST despite the `@link`
|
|
104
103
|
// _definition_ not being provided. And the reason that is true is that as we later _add_ the `@link` definition, we
|
|
105
104
|
// will need to check if `link_Purpose` needs to be added or not, but when it is already present, we check it's definition
|
|
106
105
|
// is the expected, but that check will unexpected fail if we haven't finished "building" said type definition.
|
|
@@ -215,7 +214,7 @@ function buildNamedTypeAndDirectivesShallow(documentNode: DocumentNode, schema:
|
|
|
215
214
|
let type = schema.type(definitionNode.name.value);
|
|
216
215
|
// Note that the type may already exists due to an extension having been processed first, but we know we
|
|
217
216
|
// have seen 2 definitions (which is invalid) if the definition has `preserverEmptyDefnition` already set
|
|
218
|
-
// since it's only set for definitions, not extensions.
|
|
217
|
+
// since it's only set for definitions, not extensions.
|
|
219
218
|
// Also note that we allow to redefine built-ins.
|
|
220
219
|
if (!type || type.isBuiltIn) {
|
|
221
220
|
type = schema.addType(newNamedType(withoutTrailingDefinition(definitionNode.kind), definitionNode.name.value));
|
|
@@ -332,9 +331,23 @@ function buildAppliedDirectives(
|
|
|
332
331
|
for (const directive of elementNode.directives ?? []) {
|
|
333
332
|
withNodeAttachedToError(
|
|
334
333
|
() => {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
334
|
+
/**
|
|
335
|
+
* If we are at the schemaDefinition level of a federation schema, it's possible that some directives
|
|
336
|
+
* will not be added until after the federation calls completeSchema. In that case, we want to wait
|
|
337
|
+
* until after completeSchema is called before we try to apply those directives.
|
|
338
|
+
*/
|
|
339
|
+
if (element !== element.schema().schemaDefinition || directive.name.value === 'link' || !element.schema().blueprint.applyDirectivesAfterParsing()) {
|
|
340
|
+
const d = element.applyDirective(directive.name.value, buildArgs(directive));
|
|
341
|
+
d.setOfExtension(extension);
|
|
342
|
+
d.sourceAST = directive;
|
|
343
|
+
} else {
|
|
344
|
+
element.addUnappliedDirective({
|
|
345
|
+
extension,
|
|
346
|
+
directive,
|
|
347
|
+
args: buildArgs(directive),
|
|
348
|
+
nameOrDef: directive.name.value,
|
|
349
|
+
});
|
|
350
|
+
}
|
|
338
351
|
},
|
|
339
352
|
directive,
|
|
340
353
|
errors,
|
package/src/coreSpec.ts
CHANGED
|
@@ -2,9 +2,8 @@ import { ASTNode, DirectiveLocation, GraphQLError, StringValueNode } from "graph
|
|
|
2
2
|
import { URL } from "url";
|
|
3
3
|
import { CoreFeature, Directive, DirectiveDefinition, EnumType, ErrGraphQLAPISchemaValidationFailed, ErrGraphQLValidationFailed, InputType, ListType, NamedType, NonNullType, ScalarType, Schema, SchemaDefinition, SchemaElement, sourceASTs } from "./definitions";
|
|
4
4
|
import { sameType } from "./types";
|
|
5
|
-
import { err } from '@apollo/core-schema';
|
|
6
5
|
import { assert, firstOf } from './utils';
|
|
7
|
-
import { ERRORS } from "./error";
|
|
6
|
+
import { aggregateError, ERRORS } from "./error";
|
|
8
7
|
import { valueToString } from "./values";
|
|
9
8
|
import { coreFeatureDefinitionIfKnown, registerKnownFeature } from "./knownCoreFeatures";
|
|
10
9
|
import { didYouMean, suggestionList } from "./suggestions";
|
|
@@ -15,11 +14,7 @@ export const linkIdentity = 'https://specs.apollo.dev/link';
|
|
|
15
14
|
|
|
16
15
|
export const linkDirectiveDefaultName = 'link';
|
|
17
16
|
|
|
18
|
-
export const ErrCoreCheckFailed = (causes:
|
|
19
|
-
err('CheckFailed', {
|
|
20
|
-
message: 'one or more checks failed',
|
|
21
|
-
causes
|
|
22
|
-
})
|
|
17
|
+
export const ErrCoreCheckFailed = (causes: GraphQLError[]) => aggregateError('CheckFailed', 'one or more checks failed', causes);
|
|
23
18
|
|
|
24
19
|
function buildError(message: string): Error {
|
|
25
20
|
// Maybe not the right error for this?
|