@apollo/federation-internals 2.7.8 → 2.8.0-alpha.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/dist/directiveAndTypeSpecification.d.ts +13 -1
- package/dist/directiveAndTypeSpecification.d.ts.map +1 -1
- package/dist/directiveAndTypeSpecification.js +2 -2
- package/dist/directiveAndTypeSpecification.js.map +1 -1
- package/dist/error.d.ts +6 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +12 -0
- package/dist/error.js.map +1 -1
- package/dist/extractSubgraphsFromSupergraph.d.ts +1 -1
- package/dist/extractSubgraphsFromSupergraph.d.ts.map +1 -1
- package/dist/extractSubgraphsFromSupergraph.js +62 -7
- package/dist/extractSubgraphsFromSupergraph.js.map +1 -1
- package/dist/federation.d.ts +15 -2
- package/dist/federation.d.ts.map +1 -1
- package/dist/federation.js +394 -4
- package/dist/federation.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/operations.d.ts +10 -8
- package/dist/operations.d.ts.map +1 -1
- package/dist/operations.js +37 -14
- package/dist/operations.js.map +1 -1
- package/dist/specs/contextSpec.d.ts +20 -0
- package/dist/specs/contextSpec.d.ts.map +1 -0
- package/dist/specs/contextSpec.js +62 -0
- package/dist/specs/contextSpec.js.map +1 -0
- package/dist/specs/federationSpec.d.ts +5 -2
- package/dist/specs/federationSpec.d.ts.map +1 -1
- package/dist/specs/federationSpec.js +9 -1
- package/dist/specs/federationSpec.js.map +1 -1
- package/dist/specs/joinSpec.d.ts +6 -0
- package/dist/specs/joinSpec.d.ts.map +1 -1
- package/dist/specs/joinSpec.js +11 -1
- package/dist/specs/joinSpec.js.map +1 -1
- package/dist/supergraphs.d.ts +4 -0
- package/dist/supergraphs.d.ts.map +1 -1
- package/dist/supergraphs.js +35 -2
- package/dist/supergraphs.js.map +1 -1
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +39 -1
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/directiveAndTypeSpecification.ts +8 -1
- package/src/error.ts +42 -0
- package/src/extractSubgraphsFromSupergraph.ts +76 -14
- package/src/federation.ts +593 -10
- package/src/index.ts +1 -0
- package/src/operations.ts +48 -21
- package/src/specs/contextSpec.ts +87 -0
- package/src/specs/federationSpec.ts +10 -1
- package/src/specs/joinSpec.ts +27 -3
- package/src/supergraphs.ts +37 -1
- package/src/utils.ts +38 -0
|
@@ -40,7 +40,7 @@ import { parseSelectionSet } from "./operations";
|
|
|
40
40
|
import fs from 'fs';
|
|
41
41
|
import path from 'path';
|
|
42
42
|
import { validateStringContainsBoolean } from "./utils";
|
|
43
|
-
import { errorCauses, printErrors } from ".";
|
|
43
|
+
import { CONTEXT_VERSIONS, ContextSpecDefinition, DirectiveDefinition, errorCauses, isFederationDirectiveDefinedInSchema, printErrors } from ".";
|
|
44
44
|
|
|
45
45
|
function filteredTypes(
|
|
46
46
|
supergraph: Schema,
|
|
@@ -193,7 +193,7 @@ function typesUsedInFederationDirective(fieldSet: string | undefined, parentType
|
|
|
193
193
|
return usedTypes;
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
export function extractSubgraphsFromSupergraph(supergraph: Schema, validateExtractedSubgraphs: boolean = true): Subgraphs {
|
|
196
|
+
export function extractSubgraphsFromSupergraph(supergraph: Schema, validateExtractedSubgraphs: boolean = true): [Subgraphs, Map<string, string>] {
|
|
197
197
|
const [coreFeatures, joinSpec] = validateSupergraph(supergraph);
|
|
198
198
|
const isFed1 = joinSpec.version.equals(new FeatureVersion(0, 1));
|
|
199
199
|
try {
|
|
@@ -212,6 +212,17 @@ export function extractSubgraphsFromSupergraph(supergraph: Schema, validateExtra
|
|
|
212
212
|
return subgraph;
|
|
213
213
|
};
|
|
214
214
|
|
|
215
|
+
const subgraphNameToGraphEnumValue = new Map<string, string>();
|
|
216
|
+
for (const [k, v] of graphEnumNameToSubgraphName.entries()) {
|
|
217
|
+
subgraphNameToGraphEnumValue.set(v, k);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const getSubgraphEnumValue = (subgraphName: string): string => {
|
|
221
|
+
const enumValue = subgraphNameToGraphEnumValue.get(subgraphName);
|
|
222
|
+
assert(enumValue, () => `Invalid subgraph name ${subgraphName} found: does not match a subgraph defined in the @join__Graph enum`);
|
|
223
|
+
return enumValue;
|
|
224
|
+
}
|
|
225
|
+
|
|
215
226
|
const types = filteredTypes(supergraph, joinSpec, coreFeatures.coreDefinition);
|
|
216
227
|
const args: ExtractArguments = {
|
|
217
228
|
supergraph,
|
|
@@ -219,6 +230,7 @@ export function extractSubgraphsFromSupergraph(supergraph: Schema, validateExtra
|
|
|
219
230
|
joinSpec,
|
|
220
231
|
filteredTypes: types,
|
|
221
232
|
getSubgraph,
|
|
233
|
+
getSubgraphEnumValue,
|
|
222
234
|
};
|
|
223
235
|
if (isFed1) {
|
|
224
236
|
extractSubgraphsFromFed1Supergraph(args);
|
|
@@ -241,7 +253,7 @@ export function extractSubgraphsFromSupergraph(supergraph: Schema, validateExtra
|
|
|
241
253
|
}
|
|
242
254
|
}
|
|
243
255
|
|
|
244
|
-
return subgraphs;
|
|
256
|
+
return [subgraphs, subgraphNameToGraphEnumValue];
|
|
245
257
|
} catch (e) {
|
|
246
258
|
let error = e;
|
|
247
259
|
let subgraph: Subgraph | undefined = undefined;
|
|
@@ -281,6 +293,7 @@ type ExtractArguments = {
|
|
|
281
293
|
joinSpec: JoinSpecDefinition,
|
|
282
294
|
filteredTypes: NamedType[],
|
|
283
295
|
getSubgraph: (application: Directive<any, { graph?: string }>) => Subgraph | undefined,
|
|
296
|
+
getSubgraphEnumValue: (subgraphName: string) => string
|
|
284
297
|
}
|
|
285
298
|
|
|
286
299
|
type SubgraphTypeInfo<T extends NamedType> = Map<string, { type: T, subgraph: Subgraph }>;
|
|
@@ -297,12 +310,13 @@ type TypesInfo = {
|
|
|
297
310
|
unionTypes: TypeInfo<UnionType>[],
|
|
298
311
|
};
|
|
299
312
|
|
|
300
|
-
function addAllEmptySubgraphTypes({
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
313
|
+
function addAllEmptySubgraphTypes(args: ExtractArguments): TypesInfo {
|
|
314
|
+
const {
|
|
315
|
+
supergraph,
|
|
316
|
+
joinSpec,
|
|
317
|
+
filteredTypes,
|
|
318
|
+
getSubgraph,
|
|
319
|
+
} = args;
|
|
306
320
|
const typeDirective = joinSpec.typeDirective(supergraph);
|
|
307
321
|
|
|
308
322
|
const objOrItfTypes: TypeInfo<ObjectType | InterfaceType>[] = [];
|
|
@@ -316,16 +330,16 @@ function addAllEmptySubgraphTypes({
|
|
|
316
330
|
// (on top of it making sense code-wise since both type behave exactly the same for most of what we're doing here).
|
|
317
331
|
case 'InterfaceType':
|
|
318
332
|
case 'ObjectType':
|
|
319
|
-
objOrItfTypes.push({ type, subgraphsInfo: addEmptyType(type, type.appliedDirectivesOf(typeDirective),
|
|
333
|
+
objOrItfTypes.push({ type, subgraphsInfo: addEmptyType(type, type.appliedDirectivesOf(typeDirective), args) });
|
|
320
334
|
break;
|
|
321
335
|
case 'InputObjectType':
|
|
322
|
-
inputObjTypes.push({ type, subgraphsInfo: addEmptyType(type, type.appliedDirectivesOf(typeDirective),
|
|
336
|
+
inputObjTypes.push({ type, subgraphsInfo: addEmptyType(type, type.appliedDirectivesOf(typeDirective), args) });
|
|
323
337
|
break;
|
|
324
338
|
case 'EnumType':
|
|
325
|
-
enumTypes.push({ type, subgraphsInfo: addEmptyType(type, type.appliedDirectivesOf(typeDirective),
|
|
339
|
+
enumTypes.push({ type, subgraphsInfo: addEmptyType(type, type.appliedDirectivesOf(typeDirective), args) });
|
|
326
340
|
break;
|
|
327
341
|
case 'UnionType':
|
|
328
|
-
unionTypes.push({ type, subgraphsInfo: addEmptyType(type, type.appliedDirectivesOf(typeDirective),
|
|
342
|
+
unionTypes.push({ type, subgraphsInfo: addEmptyType(type, type.appliedDirectivesOf(typeDirective), args) });
|
|
329
343
|
break;
|
|
330
344
|
case 'ScalarType':
|
|
331
345
|
// Scalar are a bit special in that they don't have any sub-component, so we don't track them beyond adding them to the
|
|
@@ -350,8 +364,9 @@ function addAllEmptySubgraphTypes({
|
|
|
350
364
|
function addEmptyType<T extends NamedType>(
|
|
351
365
|
type: T,
|
|
352
366
|
typeApplications: Directive<T, JoinTypeDirectiveArguments>[],
|
|
353
|
-
|
|
367
|
+
args: ExtractArguments,
|
|
354
368
|
): SubgraphTypeInfo<T> {
|
|
369
|
+
const { supergraph, getSubgraph, getSubgraphEnumValue } = args;
|
|
355
370
|
// In fed2, we always mark all types with `@join__type` but making sure.
|
|
356
371
|
assert(typeApplications.length > 0, `Missing @join__type on ${type}`)
|
|
357
372
|
const subgraphsInfo: SubgraphTypeInfo<T> = new Map<string, { type: T, subgraph: Subgraph }>();
|
|
@@ -382,6 +397,33 @@ function addEmptyType<T extends NamedType>(
|
|
|
382
397
|
}
|
|
383
398
|
}
|
|
384
399
|
}
|
|
400
|
+
|
|
401
|
+
const coreFeatures = supergraph.coreFeatures;
|
|
402
|
+
assert(coreFeatures, 'Should have core features');
|
|
403
|
+
const contextFeature = coreFeatures.getByIdentity(ContextSpecDefinition.identity);
|
|
404
|
+
let supergraphContextDirective: DirectiveDefinition<{ name: string}> | undefined;
|
|
405
|
+
if (contextFeature) {
|
|
406
|
+
const contextSpec = CONTEXT_VERSIONS.find(contextFeature.url.version);
|
|
407
|
+
assert(contextSpec, 'Should have context spec');
|
|
408
|
+
supergraphContextDirective = contextSpec.contextDirective(supergraph);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (supergraphContextDirective) {
|
|
412
|
+
const contextApplications = type.appliedDirectivesOf(supergraphContextDirective);
|
|
413
|
+
// for every application, apply the context directive to the correct subgraph
|
|
414
|
+
for (const application of contextApplications) {
|
|
415
|
+
const { name } = application.arguments();
|
|
416
|
+
const match = name.match(/^(.*)__([A-Za-z]\w*)$/);
|
|
417
|
+
const graph = match ? match[1] : undefined;
|
|
418
|
+
const context = match ? match[2] : undefined;
|
|
419
|
+
assert(graph, `Invalid context name ${name} found in ${application} on ${application.parent}: does not match the expected pattern`);
|
|
420
|
+
const subgraphInfo = subgraphsInfo.get(getSubgraphEnumValue(graph));
|
|
421
|
+
const contextDirective = subgraphInfo?.subgraph.metadata().contextDirective();
|
|
422
|
+
if (subgraphInfo && contextDirective && isFederationDirectiveDefinedInSchema(contextDirective)) {
|
|
423
|
+
subgraphInfo.type.applyDirective(contextDirective, {name: context});
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
385
427
|
return subgraphsInfo;
|
|
386
428
|
}
|
|
387
429
|
|
|
@@ -610,6 +652,26 @@ function addSubgraphField({
|
|
|
610
652
|
if (joinFieldArgs?.provides) {
|
|
611
653
|
subgraphField.applyDirective(subgraph.metadata().providesDirective(), {'fields': joinFieldArgs.provides});
|
|
612
654
|
}
|
|
655
|
+
if (joinFieldArgs?.contextArguments) {
|
|
656
|
+
const fromContextDirective = subgraph.metadata().fromContextDirective();
|
|
657
|
+
if (!isFederationDirectiveDefinedInSchema(fromContextDirective)) {
|
|
658
|
+
throw new Error(`@fromContext directive is not defined in the subgraph schema: ${subgraph.name}`);
|
|
659
|
+
} else {
|
|
660
|
+
for (const arg of joinFieldArgs.contextArguments) {
|
|
661
|
+
// this code will remove the subgraph name from the context
|
|
662
|
+
const match = arg.context.match(/^.*__([A-Za-z]\w*)$/);
|
|
663
|
+
if (!match) {
|
|
664
|
+
throw new Error(`Invalid context argument: ${arg.context}`);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
subgraphField.addArgument(arg.name, decodeType(arg.type, subgraph.schema, subgraph.name));
|
|
668
|
+
const argOnField = subgraphField.argument(arg.name);
|
|
669
|
+
argOnField?.applyDirective(fromContextDirective, {
|
|
670
|
+
field: `\$${match[1]} ${arg.selection}`,
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
613
675
|
const external = !!joinFieldArgs?.external;
|
|
614
676
|
if (external) {
|
|
615
677
|
subgraphField.applyDirective(subgraph.metadata().externalDirective());
|