@apollo/federation-internals 2.0.0-preview.7 → 2.0.0-preview.8
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 +2 -4
- package/dist/buildSchema.d.ts.map +1 -1
- package/dist/buildSchema.js +50 -40
- package/dist/buildSchema.js.map +1 -1
- package/dist/coreSpec.d.ts +4 -2
- package/dist/coreSpec.d.ts.map +1 -1
- package/dist/coreSpec.js +107 -19
- package/dist/coreSpec.js.map +1 -1
- package/dist/definitions.d.ts +3 -0
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +72 -6
- package/dist/definitions.js.map +1 -1
- package/dist/error.d.ts +4 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +27 -1
- package/dist/error.js.map +1 -1
- package/dist/federation.d.ts +4 -0
- package/dist/federation.d.ts.map +1 -1
- package/dist/federation.js +41 -11
- package/dist/federation.js.map +1 -1
- package/dist/federationSpec.d.ts +4 -0
- package/dist/federationSpec.d.ts.map +1 -1
- package/dist/federationSpec.js +19 -2
- package/dist/federationSpec.js.map +1 -1
- package/dist/inaccessibleSpec.d.ts +3 -0
- package/dist/inaccessibleSpec.d.ts.map +1 -1
- package/dist/inaccessibleSpec.js +22 -3
- package/dist/inaccessibleSpec.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/joinSpec.d.ts +1 -0
- package/dist/joinSpec.d.ts.map +1 -1
- package/dist/joinSpec.js +18 -0
- package/dist/joinSpec.js.map +1 -1
- package/dist/knownCoreFeatures.d.ts +4 -0
- package/dist/knownCoreFeatures.d.ts.map +1 -0
- package/dist/knownCoreFeatures.js +16 -0
- package/dist/knownCoreFeatures.js.map +1 -0
- package/dist/tagSpec.d.ts +1 -0
- package/dist/tagSpec.d.ts.map +1 -1
- package/dist/tagSpec.js +5 -0
- package/dist/tagSpec.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/coreSpec.test.ts +100 -0
- package/src/__tests__/definitions.test.ts +75 -0
- package/src/__tests__/removeInaccessibleElements.test.ts +1 -1
- package/src/__tests__/schemaUpgrader.test.ts +3 -2
- package/src/__tests__/subgraphValidation.test.ts +63 -4
- package/src/buildSchema.ts +97 -50
- package/src/coreSpec.ts +124 -21
- package/src/definitions.ts +99 -7
- package/src/error.ts +40 -0
- package/src/federation.ts +67 -12
- package/src/federationSpec.ts +26 -1
- package/src/inaccessibleSpec.ts +26 -10
- package/src/index.ts +1 -0
- package/src/joinSpec.ts +19 -0
- package/src/knownCoreFeatures.ts +13 -0
- package/src/tagSpec.ts +7 -0
- package/tsconfig.test.tsbuildinfo +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knownCoreFeatures.d.ts","sourceRoot":"","sources":["../src/knownCoreFeatures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI/E,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,kBAAkB,QAInE;AAED,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,UAAU,GAAG,iBAAiB,GAAG,SAAS,CAE3F"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.coreFeatureDefinitionIfKnown = exports.registerKnownFeature = void 0;
|
|
4
|
+
const registeredFeatures = new Map();
|
|
5
|
+
function registerKnownFeature(definitions) {
|
|
6
|
+
if (!registeredFeatures.has(definitions.identity)) {
|
|
7
|
+
registeredFeatures.set(definitions.identity, definitions);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.registerKnownFeature = registerKnownFeature;
|
|
11
|
+
function coreFeatureDefinitionIfKnown(url) {
|
|
12
|
+
var _a;
|
|
13
|
+
return (_a = registeredFeatures.get(url.identity)) === null || _a === void 0 ? void 0 : _a.find(url.version);
|
|
14
|
+
}
|
|
15
|
+
exports.coreFeatureDefinitionIfKnown = coreFeatureDefinitionIfKnown;
|
|
16
|
+
//# sourceMappingURL=knownCoreFeatures.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knownCoreFeatures.js","sourceRoot":"","sources":["../src/knownCoreFeatures.ts"],"names":[],"mappings":";;;AAEA,MAAM,kBAAkB,GAAoC,IAAI,GAAG,EAAE,CAAC;AAEtE,SAAgB,oBAAoB,CAAC,WAA+B;IAClE,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE;QACjD,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;KAC3D;AACH,CAAC;AAJD,oDAIC;AAED,SAAgB,4BAA4B,CAAC,GAAe;;IAC1D,OAAO,MAAA,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,0CAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACjE,CAAC;AAFD,oEAEC"}
|
package/dist/tagSpec.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export declare class TagSpecDefinition extends FeatureDefinition {
|
|
|
10
10
|
name: string;
|
|
11
11
|
}>;
|
|
12
12
|
checkCompatibleDirective(definition: DirectiveDefinition): GraphQLError | undefined;
|
|
13
|
+
allElementNames(): string[];
|
|
13
14
|
}
|
|
14
15
|
export declare const TAG_VERSIONS: FeatureDefinitions<TagSpecDefinition>;
|
|
15
16
|
//# sourceMappingURL=tagSpec.d.ts.map
|
package/dist/tagSpec.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tagSpec.d.ts","sourceRoot":"","sources":["../src/tagSpec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAc,cAAc,EAAE,MAAM,YAAY,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAe,MAAM,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"tagSpec.d.ts","sourceRoot":"","sources":["../src/tagSpec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAc,cAAc,EAAE,MAAM,YAAY,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAe,MAAM,EAAE,MAAM,eAAe,CAAC;AAKzE,eAAO,MAAM,WAAW,iCAAiC,CAAC;AAE1D,eAAO,MAAM,YAAY,qBAKxB,CAAC;AAIF,qBAAa,iBAAkB,SAAQ,iBAAiB;gBAC1C,OAAO,EAAE,cAAc;IAInC,mBAAmB,CAAC,MAAM,EAAE,MAAM;IAMlC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC;IAIjE,wBAAwB,CAAC,UAAU,EAAE,mBAAmB,GAAG,YAAY,GAAG,SAAS;IAcnF,eAAe,IAAI,MAAM,EAAE;CAG5B;AAED,eAAO,MAAM,YAAY,uCAC8B,CAAC"}
|
package/dist/tagSpec.js
CHANGED
|
@@ -5,6 +5,7 @@ const graphql_1 = require("graphql");
|
|
|
5
5
|
const coreSpec_1 = require("./coreSpec");
|
|
6
6
|
const definitions_1 = require("./definitions");
|
|
7
7
|
const error_1 = require("./error");
|
|
8
|
+
const knownCoreFeatures_1 = require("./knownCoreFeatures");
|
|
8
9
|
const types_1 = require("./types");
|
|
9
10
|
exports.tagIdentity = 'https://specs.apollo.dev/tag';
|
|
10
11
|
exports.tagLocations = [
|
|
@@ -38,8 +39,12 @@ class TagSpecDefinition extends coreSpec_1.FeatureDefinition {
|
|
|
38
39
|
}
|
|
39
40
|
return undefined;
|
|
40
41
|
}
|
|
42
|
+
allElementNames() {
|
|
43
|
+
return ["@tag"];
|
|
44
|
+
}
|
|
41
45
|
}
|
|
42
46
|
exports.TagSpecDefinition = TagSpecDefinition;
|
|
43
47
|
exports.TAG_VERSIONS = new coreSpec_1.FeatureDefinitions(exports.tagIdentity)
|
|
44
48
|
.add(new TagSpecDefinition(new coreSpec_1.FeatureVersion(0, 1)));
|
|
49
|
+
(0, knownCoreFeatures_1.registerKnownFeature)(exports.TAG_VERSIONS);
|
|
45
50
|
//# sourceMappingURL=tagSpec.js.map
|
package/dist/tagSpec.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tagSpec.js","sourceRoot":"","sources":["../src/tagSpec.ts"],"names":[],"mappings":";;;AAAA,qCAA0D;AAC1D,yCAA+F;AAC/F,+CAAyE;AACzE,mCAAiC;AACjC,mCAAmC;AAEtB,QAAA,WAAW,GAAG,8BAA8B,CAAC;AAE7C,QAAA,YAAY,GAAG;IAC1B,2BAAiB,CAAC,gBAAgB;IAClC,2BAAiB,CAAC,MAAM;IACxB,2BAAiB,CAAC,SAAS;IAC3B,2BAAiB,CAAC,KAAK;CACxB,CAAC;AAEF,MAAM,oBAAoB,GAAG,2FAA2F,CAAC;AAEzH,MAAa,iBAAkB,SAAQ,4BAAiB;IACtD,YAAY,OAAuB;QACjC,KAAK,CAAC,IAAI,qBAAU,CAAC,mBAAW,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,mBAAmB,CAAC,MAAc;QAChC,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,YAAY,CAAC,GAAG,oBAAY,CAAC,CAAC;QACjF,SAAS,CAAC,UAAU,GAAG,IAAI,CAAC;QAC5B,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,yBAAW,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,YAAY,CAAC,MAAc;QACzB,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAE,CAAC;IACxC,CAAC;IAED,wBAAwB,CAAC,UAA+B;QACtD,MAAM,mBAAmB,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QAC3E,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,eAAe,GAAG,OAAO,IAAI,IAAA,gBAAQ,EAAC,OAAO,CAAC,IAAK,EAAE,IAAI,yBAAW,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QAC9G,MAAM,iBAAiB,GAAG,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,oBAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QACxF,IAAI,mBAAmB,IAAI,CAAC,eAAe,IAAI,CAAC,iBAAiB,EAAE;YACjE,OAAO,cAAM,CAAC,4BAA4B,CAAC,GAAG,CAAC;gBAC7C,OAAO,EAAE,0IAA0I,oBAAoB,EAAE;aAC1K,CACA,CAAC;SACH;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;
|
|
1
|
+
{"version":3,"file":"tagSpec.js","sourceRoot":"","sources":["../src/tagSpec.ts"],"names":[],"mappings":";;;AAAA,qCAA0D;AAC1D,yCAA+F;AAC/F,+CAAyE;AACzE,mCAAiC;AACjC,2DAA2D;AAC3D,mCAAmC;AAEtB,QAAA,WAAW,GAAG,8BAA8B,CAAC;AAE7C,QAAA,YAAY,GAAG;IAC1B,2BAAiB,CAAC,gBAAgB;IAClC,2BAAiB,CAAC,MAAM;IACxB,2BAAiB,CAAC,SAAS;IAC3B,2BAAiB,CAAC,KAAK;CACxB,CAAC;AAEF,MAAM,oBAAoB,GAAG,2FAA2F,CAAC;AAEzH,MAAa,iBAAkB,SAAQ,4BAAiB;IACtD,YAAY,OAAuB;QACjC,KAAK,CAAC,IAAI,qBAAU,CAAC,mBAAW,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,mBAAmB,CAAC,MAAc;QAChC,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,YAAY,CAAC,GAAG,oBAAY,CAAC,CAAC;QACjF,SAAS,CAAC,UAAU,GAAG,IAAI,CAAC;QAC5B,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,yBAAW,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,YAAY,CAAC,MAAc;QACzB,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAE,CAAC;IACxC,CAAC;IAED,wBAAwB,CAAC,UAA+B;QACtD,MAAM,mBAAmB,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QAC3E,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,eAAe,GAAG,OAAO,IAAI,IAAA,gBAAQ,EAAC,OAAO,CAAC,IAAK,EAAE,IAAI,yBAAW,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QAC9G,MAAM,iBAAiB,GAAG,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,oBAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QACxF,IAAI,mBAAmB,IAAI,CAAC,eAAe,IAAI,CAAC,iBAAiB,EAAE;YACjE,OAAO,cAAM,CAAC,4BAA4B,CAAC,GAAG,CAAC;gBAC7C,OAAO,EAAE,0IAA0I,oBAAoB,EAAE;aAC1K,CACA,CAAC;SACH;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,eAAe;QACb,OAAO,CAAC,MAAM,CAAC,CAAC;IAClB,CAAC;CACF;AAhCD,8CAgCC;AAEY,QAAA,YAAY,GAAG,IAAI,6BAAkB,CAAoB,mBAAW,CAAC;KAC/E,GAAG,CAAC,IAAI,iBAAiB,CAAC,IAAI,yBAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAExD,IAAA,wCAAoB,EAAC,oBAAY,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apollo/federation-internals",
|
|
3
|
-
"version": "2.0.0-preview.
|
|
3
|
+
"version": "2.0.0-preview.8",
|
|
4
4
|
"description": "Apollo Federation internal utilities",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"graphql": "^16.0.0"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "516a30d879b4bde5945adb55b80d0f64118c322f"
|
|
37
37
|
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { DocumentNode, GraphQLError } from "graphql";
|
|
2
|
+
import gql from "graphql-tag";
|
|
3
|
+
import { buildSubgraph } from "../federation";
|
|
4
|
+
import { errorCauses } from "../definitions";
|
|
5
|
+
import { assert } from "../utils";
|
|
6
|
+
|
|
7
|
+
function expectErrors(
|
|
8
|
+
subgraphDefs: DocumentNode,
|
|
9
|
+
expectedErrorMessages: string[],
|
|
10
|
+
) {
|
|
11
|
+
let thrownError: Error | undefined = undefined;
|
|
12
|
+
expect(() => {
|
|
13
|
+
try {
|
|
14
|
+
// Note: we use buildSubgraph because currently it's the only one that does auto-magic import of
|
|
15
|
+
// directive definition, and we don't want to bother with adding the @link definition to every
|
|
16
|
+
// example.
|
|
17
|
+
buildSubgraph('S', '', subgraphDefs)
|
|
18
|
+
} catch (e) {
|
|
19
|
+
// Kind-of ugly, but if Jest has a better option, I haven't found it.
|
|
20
|
+
thrownError = e;
|
|
21
|
+
throw e;
|
|
22
|
+
}
|
|
23
|
+
}).toThrow(GraphQLError);
|
|
24
|
+
|
|
25
|
+
assert(thrownError, 'Should have thrown');
|
|
26
|
+
const causes = errorCauses(thrownError);
|
|
27
|
+
assert(causes, 'Should have some causes');
|
|
28
|
+
// Note: all the received message with start with "[S] <rest of message>", so the `slice` below
|
|
29
|
+
// strips the extra prefix. This avoid leaking the subgraph name to leak to the tests themselves.
|
|
30
|
+
expect(causes.map((e) => e.message.slice(4))).toStrictEqual(expectedErrorMessages);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
describe('@link(import:) argument', () => {
|
|
34
|
+
test('errors on misformed values', () => {
|
|
35
|
+
const schema = gql`
|
|
36
|
+
extend schema @link(
|
|
37
|
+
url: "https://specs.apollo.dev/federation/v2.0",
|
|
38
|
+
import: [
|
|
39
|
+
2,
|
|
40
|
+
{ foo: "bar" },
|
|
41
|
+
{ name: "@key", badName: "foo"},
|
|
42
|
+
{ name: 42 },
|
|
43
|
+
{ as: "bar" },
|
|
44
|
+
]
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
type Query {
|
|
48
|
+
q: Int
|
|
49
|
+
}
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
expectErrors(schema, [
|
|
53
|
+
'Invalid sub-value 2 for @link(import:) argument: values should be either strings or input object values of the form { name: "<importedElement>", as: "<alias>" }.',
|
|
54
|
+
'Unknown field "foo" for sub-value {foo: "bar"} of @link(import:) argument.',
|
|
55
|
+
'Unknown field "badName" for sub-value {name: "@key", badName: "foo"} of @link(import:) argument.',
|
|
56
|
+
'Invalid value for the "name" field for sub-value {name: 42} of @link(import:) argument: must be a string.',
|
|
57
|
+
'Invalid sub-value {as: "bar"} for @link(import:) argument: missing mandatory "name" field.',
|
|
58
|
+
]);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('errors on mismatch between name and alias', () => {
|
|
62
|
+
const schema = gql`
|
|
63
|
+
extend schema @link(
|
|
64
|
+
url: "https://specs.apollo.dev/federation/v2.0",
|
|
65
|
+
import: [
|
|
66
|
+
{ name: "@key", as: "myKey" },
|
|
67
|
+
{ name: "FieldSet", as: "@fieldSet" },
|
|
68
|
+
]
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
type Query {
|
|
72
|
+
q: Int
|
|
73
|
+
}
|
|
74
|
+
`;
|
|
75
|
+
|
|
76
|
+
expectErrors(schema, [
|
|
77
|
+
'Invalid @link import renaming: directive "@key" imported name should start with a \'@\' character, but got "myKey".',
|
|
78
|
+
'Invalid @link import renaming: type "FieldSet" imported name should not start with a \'@\' character, but got "@fieldSet" (or, if @FieldSet is a directive, then it should be referred to with a \'@\').',
|
|
79
|
+
]);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test('errors on importing unknown elements for known features', () => {
|
|
83
|
+
const schema = gql`
|
|
84
|
+
extend schema @link(
|
|
85
|
+
url: "https://specs.apollo.dev/federation/v2.0",
|
|
86
|
+
import: [ "@foo", "key", { name: "@sharable" } ]
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
type Query {
|
|
90
|
+
q: Int
|
|
91
|
+
}
|
|
92
|
+
`;
|
|
93
|
+
|
|
94
|
+
expectErrors(schema, [
|
|
95
|
+
'Cannot import unknown element "@foo".',
|
|
96
|
+
'Cannot import unknown element "key". Did you mean directive "@key"?',
|
|
97
|
+
'Cannot import unknown element "@sharable\". Did you mean "@shareable"?',
|
|
98
|
+
]);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
EnumType,
|
|
8
8
|
SchemaElement,
|
|
9
9
|
UnionType,
|
|
10
|
+
InputObjectType,
|
|
10
11
|
} from '../../dist/definitions';
|
|
11
12
|
import {
|
|
12
13
|
printSchema as printGraphQLjsSchema
|
|
@@ -612,3 +613,77 @@ test('correctly convert to a graphQL-js schema', () => {
|
|
|
612
613
|
const graphqQLSchema = schema.toGraphQLJSSchema();
|
|
613
614
|
expect(printGraphQLjsSchema(graphqQLSchema)).toMatchString(sdl);
|
|
614
615
|
});
|
|
616
|
+
|
|
617
|
+
test('retrieving elements by coordinate', () => {
|
|
618
|
+
const sdl = `
|
|
619
|
+
directive @foo(bar: Int) on FIELD
|
|
620
|
+
|
|
621
|
+
type Query {
|
|
622
|
+
t: T
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
type T {
|
|
626
|
+
f1(x: Int): String
|
|
627
|
+
f2: String
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
interface I {
|
|
631
|
+
i: String
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
input O {
|
|
635
|
+
x: Int
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
enum E {
|
|
639
|
+
FOO
|
|
640
|
+
BAR
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
scalar Date
|
|
644
|
+
`;
|
|
645
|
+
const schema = parseSchema(sdl);
|
|
646
|
+
|
|
647
|
+
expect(schema.elementByCoordinate('Query')).toBe(schema.schemaDefinition.rootType('query'));
|
|
648
|
+
expect(schema.elementByCoordinate('Query.t')).toBe(schema.schemaDefinition.rootType('query')?.field('t'));
|
|
649
|
+
|
|
650
|
+
const typeT = schema.type('T') as ObjectType;
|
|
651
|
+
expect(schema.elementByCoordinate('T')).toBe(typeT);
|
|
652
|
+
expect(schema.elementByCoordinate('T.f1')).toBe(typeT.field('f1'));
|
|
653
|
+
expect(schema.elementByCoordinate('T.f2')).toBe(typeT.field('f2'));
|
|
654
|
+
expect(schema.elementByCoordinate('T.f1(x:)')).toBe(typeT.field('f1')?.argument('x'));
|
|
655
|
+
|
|
656
|
+
const typeI = schema.type('I') as InterfaceType;
|
|
657
|
+
expect(schema.elementByCoordinate('I')).toBe(typeI);
|
|
658
|
+
expect(schema.elementByCoordinate('I.i')).toBe(typeI.field('i'));
|
|
659
|
+
|
|
660
|
+
const typeO = schema.type('O') as InputObjectType;
|
|
661
|
+
expect(schema.elementByCoordinate('O')).toBe(typeO);
|
|
662
|
+
expect(schema.elementByCoordinate('O.x')).toBe(typeO.field('x'));
|
|
663
|
+
|
|
664
|
+
const typeE = schema.type('E') as EnumType;
|
|
665
|
+
expect(schema.elementByCoordinate('E')).toBe(typeE);
|
|
666
|
+
expect(schema.elementByCoordinate('E.FOO')).toBe(typeE.value('FOO'));
|
|
667
|
+
|
|
668
|
+
expect(schema.elementByCoordinate('Date')).toBe(schema.type('Date'));
|
|
669
|
+
|
|
670
|
+
const directiveFoo = schema.directive('foo')!;
|
|
671
|
+
expect(schema.elementByCoordinate('@foo')).toBe(directiveFoo);
|
|
672
|
+
expect(schema.elementByCoordinate('@foo(bar:)')).toBe(directiveFoo.argument('bar'));
|
|
673
|
+
|
|
674
|
+
expect(schema.elementByCoordinate('SomeType')).toBeUndefined();
|
|
675
|
+
expect(schema.elementByCoordinate('T.f3')).toBeUndefined();
|
|
676
|
+
expect(schema.elementByCoordinate('T.f1(y:)')).toBeUndefined();
|
|
677
|
+
expect(schema.elementByCoordinate('I.j')).toBeUndefined();
|
|
678
|
+
expect(schema.elementByCoordinate('I.j(x:)')).toBeUndefined();
|
|
679
|
+
expect(schema.elementByCoordinate('O.z')).toBeUndefined();
|
|
680
|
+
expect(schema.elementByCoordinate('@bar')).toBeUndefined();
|
|
681
|
+
expect(schema.elementByCoordinate('@foo(unknown:)')).toBeUndefined();
|
|
682
|
+
|
|
683
|
+
expect(() => schema.elementByCoordinate('foo bar')).toThrow();
|
|
684
|
+
expect(() => schema.elementByCoordinate('@foo.bar')).toThrow();
|
|
685
|
+
// Note that because 'O' is an input type, it's field can't have args
|
|
686
|
+
expect(() => schema.elementByCoordinate('O.x(foo:)')).toThrow();
|
|
687
|
+
// Note that because 'Date' is a scalar, it cannot have fields
|
|
688
|
+
expect(() => schema.elementByCoordinate('Date.bar')).toThrow();
|
|
689
|
+
})
|
|
@@ -181,7 +181,7 @@ describe('removeInaccessibleElements', () => {
|
|
|
181
181
|
expect(() => {
|
|
182
182
|
removeInaccessibleElements(schema);
|
|
183
183
|
}).toThrow(
|
|
184
|
-
`Field Query.fooField returns
|
|
184
|
+
`Field "Query.fooField" returns @inaccessible type "Foo" without being marked @inaccessible itself`,
|
|
185
185
|
);
|
|
186
186
|
});
|
|
187
187
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FEDERATION2_LINK_WTH_FULL_IMPORTS } from '..';
|
|
1
2
|
import { buildSubgraph, Subgraphs } from '../federation';
|
|
2
3
|
import { UpgradeChangeID, UpgradeResult, upgradeSubgraphsIfNecessary } from '../schemaUpgrader';
|
|
3
4
|
import './matchers';
|
|
@@ -91,7 +92,7 @@ test('upgrade complex schema', () => {
|
|
|
91
92
|
expect(res.subgraphs?.get('s1')?.toString()).toMatchString(`
|
|
92
93
|
schema
|
|
93
94
|
@link(url: "https://specs.apollo.dev/link/v1.0")
|
|
94
|
-
|
|
95
|
+
${FEDERATION2_LINK_WTH_FULL_IMPORTS}
|
|
95
96
|
{
|
|
96
97
|
query: Query
|
|
97
98
|
}
|
|
@@ -148,7 +149,7 @@ test('update federation directive non-string arguments', () => {
|
|
|
148
149
|
expect(res.subgraphs?.get('s')?.toString()).toMatchString(`
|
|
149
150
|
schema
|
|
150
151
|
@link(url: "https://specs.apollo.dev/link/v1.0")
|
|
151
|
-
|
|
152
|
+
${FEDERATION2_LINK_WTH_FULL_IMPORTS}
|
|
152
153
|
{
|
|
153
154
|
query: Query
|
|
154
155
|
}
|
|
@@ -6,10 +6,17 @@ import { asFed2SubgraphDocument, buildSubgraph } from "../federation"
|
|
|
6
6
|
// Builds the provided subgraph (using name 'S' for the subgraph) and, if the
|
|
7
7
|
// subgraph is invalid/has errors, return those errors as a list of [code, message].
|
|
8
8
|
// If the subgraph is valid, return undefined.
|
|
9
|
-
function buildForErrors(
|
|
9
|
+
function buildForErrors(
|
|
10
|
+
subgraphDefs: DocumentNode,
|
|
11
|
+
options?: {
|
|
12
|
+
subgraphName?: string,
|
|
13
|
+
asFed2?: boolean,
|
|
14
|
+
}
|
|
15
|
+
): [string, string][] | undefined {
|
|
10
16
|
try {
|
|
11
|
-
const doc = asFed2SubgraphDocument(subgraphDefs);
|
|
12
|
-
|
|
17
|
+
const doc = (options?.asFed2 ?? true) ? asFed2SubgraphDocument(subgraphDefs) : subgraphDefs;
|
|
18
|
+
const name = options?.subgraphName ?? 'S';
|
|
19
|
+
buildSubgraph(name, `http://${name}`, doc).validate();
|
|
13
20
|
return undefined;
|
|
14
21
|
} catch (e) {
|
|
15
22
|
const causes = errorCauses(e);
|
|
@@ -436,7 +443,6 @@ describe('root types', () => {
|
|
|
436
443
|
});
|
|
437
444
|
});
|
|
438
445
|
|
|
439
|
-
|
|
440
446
|
it('validates all implementations of interface field have same type if any has @external', () => {
|
|
441
447
|
const subgraph = gql`
|
|
442
448
|
type Query {
|
|
@@ -464,3 +470,56 @@ it('validates all implementations of interface field have same type if any has @
|
|
|
464
470
|
['INTERFACE_FIELD_IMPLEM_TYPE_MISMATCH', '[S] Some of the runtime implementations of interface field "I.f" are marked @external or have a @require ("T3.f") so all the implementations should use the same type (a current limitation of federation; see https://github.com/apollographql/federation/issues/1257), but "T1.f" and "T3.f" have type "Int" while "T2.f" has type "Int!".'],
|
|
465
471
|
]);
|
|
466
472
|
})
|
|
473
|
+
|
|
474
|
+
describe('custom error message for misnamed directives', () => {
|
|
475
|
+
it.each([
|
|
476
|
+
{ name: 'fed1', extraMsg: ' If so, note that it is a federation 2 directive but this schema is a federation 1 one. To be a federation 2 schema, it needs to @link to the federation specifcation v2.' },
|
|
477
|
+
{ name: 'fed2', extraMsg: '' },
|
|
478
|
+
|
|
479
|
+
])('has suggestions if a federation directive name is mispelled in $name', ({name, extraMsg}) => {
|
|
480
|
+
const subgraph = gql`
|
|
481
|
+
type T @keys(fields: "id") {
|
|
482
|
+
id: Int @foo
|
|
483
|
+
foo: String @sharable
|
|
484
|
+
}
|
|
485
|
+
`;
|
|
486
|
+
|
|
487
|
+
expect(buildForErrors(subgraph, { asFed2 : name === 'fed2' })).toStrictEqual([
|
|
488
|
+
['INVALID_GRAPHQL', `[S] Unknown directive "@foo".`],
|
|
489
|
+
['INVALID_GRAPHQL', `[S] Unknown directive "@sharable". Did you mean "@shareable"?${extraMsg}`],
|
|
490
|
+
['INVALID_GRAPHQL', `[S] Unknown directive "@keys". Did you mean "@key"?`],
|
|
491
|
+
]);
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
it('has suggestions if a fed2 directive is used in fed1', () => {
|
|
495
|
+
const subgraph = gql`
|
|
496
|
+
type T @key(fields: "id") {
|
|
497
|
+
id: Int
|
|
498
|
+
foo: String @shareable
|
|
499
|
+
}
|
|
500
|
+
`;
|
|
501
|
+
|
|
502
|
+
expect(buildForErrors(subgraph, { asFed2 : false })).toStrictEqual([
|
|
503
|
+
['INVALID_GRAPHQL', `[S] Unknown directive "@shareable". If you meant the \"@shareable\" federation 2 directive, note that this schema is a federation 1 schema. To be a federation 2 schema, it needs to @link to the federation specifcation v2.`],
|
|
504
|
+
]);
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
it('has suggestions if a fed2 directive is used under the wrong name (for the schema)', () => {
|
|
508
|
+
const subgraph = gql`
|
|
509
|
+
extend schema
|
|
510
|
+
@link(url: "https://specs.apollo.dev/federation/v2.0",
|
|
511
|
+
import: [ { name: "@key", as: "@myKey"} ])
|
|
512
|
+
|
|
513
|
+
type T @key(fields: "id") {
|
|
514
|
+
id: Int
|
|
515
|
+
foo: String @shareable
|
|
516
|
+
}
|
|
517
|
+
`;
|
|
518
|
+
|
|
519
|
+
// Note: it's a fed2 schema, but we manually add the @link, so we pass `asFed2: false` to avoid having added twice.
|
|
520
|
+
expect(buildForErrors(subgraph, { asFed2 : false })).toStrictEqual([
|
|
521
|
+
['INVALID_GRAPHQL', `[S] Unknown directive "@shareable". If you meant the \"@shareable\" federation directive, you should use fully-qualified name "@federation__shareable" or add "@shareable" to the \`import\` argument of the @link to the federation specification.`],
|
|
522
|
+
['INVALID_GRAPHQL', `[S] Unknown directive "@key". If you meant the "@key" federation directive, you should use "@myKey" as it is imported under that name in the @link to the federation specification of this schema.`],
|
|
523
|
+
]);
|
|
524
|
+
});
|
|
525
|
+
});
|